Skip to content

Commit

Permalink
Issue #7 - PowerShell Remoting - mostly
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamNaj committed Nov 18, 2013
1 parent 649bb84 commit 08c2339
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 9 deletions.
2 changes: 2 additions & 0 deletions Cognifide.PowerShell.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerShellIntegrations\Commandlets\Packages\InstallUpdatePackageCommand.cs" />
<Compile Include="PowerShellIntegrations\Commandlets\Remoting\ConvertFromCliXmlCommand.cs" />
<Compile Include="PowerShellIntegrations\Commandlets\Remoting\ConvertToCliXmlCommand.cs" />
<Compile Include="PowerShellIntegrations\Commandlets\Scheduler\StartTaskSchedule.cs" />
<Compile Include="PowerShellIntegrations\Commandlets\Scheduler\GetTaskSchedule.cs" />
<Compile Include="PowerShellIntegrations\Host\CognifideSitecorePowerShellSnapIn.cs">
Expand Down
33 changes: 28 additions & 5 deletions Console/Services/RemoteAutomation.asmx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,41 @@ public NameValue[] ExecuteScript(string userName, string password, string script
(current, next) => current + next)
});
}
foreach (var variable in returnVariables.Split('|'))
{
result.Add(new NameValue
result.AddRange(
returnVariables.Split('|').Select(variable => new NameValue
{
Name = variable,
Value = (scriptSession.GetVariable(variable) ?? string.Empty).ToString()
});
}
}));
return result.ToArray();
}
}

[WebMethod]
public string ExecuteScriptBlock(string userName, string password, string script)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
if (!userName.Contains("\\"))
{
userName = "sitecore\\" + userName;
}
bool loggedIn = AuthenticationManager.Login(userName, password, false);
if (!loggedIn)
{
throw new AuthenticationException("Unrecognized user or password mismatch.");
}
}

using (var scriptSession = new ScriptSession(ApplicationNames.RemoteAutomation, false))
{
scriptSession.ExecuteScriptPart(scriptSession.Settings.Prescript);
scriptSession.ExecuteScriptPart(script + "| ConvertTo-CliXml");

return scriptSession.Output.Select(p => p.Terminated ? p.Text + "\n" : p.Text).Aggregate(
(current, next) => current + next);
}
}
public class NameValue
{
public string Name { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion Console/Styles/Console.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ html {
left: 0px;
height: 100%;
width: 100%;
overflow: scroll;
overflow: auto;
}

#Content > tbody > tr > td {
Expand Down
Binary file modified Data/packages/Sitecore PowerShell Extensions-2.5.1.zip
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
----item----
version: 1
id: {23F746EC-809E-4D33-9055-F33CBA1225CA}
database: master
path: /sitecore/system/Modules/PowerShell/Script Library/Functions/Execute-RemoteSitecoreScript
parent: {E22D066A-04D0-4799-9DAD-EDD9EB07C2B2}
name: Execute-RemoteSitecoreScript
master: {00000000-0000-0000-0000-000000000000}
template: {DD22F1B3-BD87-4DB2-9E7D-F7A496888D43}
templatekey: PowerShell Script

----field----
field: {B1A94FF0-6897-47C0-9C51-AA6ACB80B1F0}
name: Script
key: script
content-length: 2223

<#
Sitecore PowerShell Remoting.

Sample Usage:
Set-SitecoreSessionConfiguration 'http://localhost' 'admin' 'b'
Execute-RemoteSitecoreScript { get-item master:\content\ }
#>

function Set-SitecoreSessionConfiguration {
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$SitecoreHost,

[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$User,

[Parameter(Position=2, Mandatory=$true, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$Password
)
$URI = $SitecoreHost+"/Console/Services/RemoteAutomation.asmx";
$GLOBAL:SpeRemoteProxy = New-WebServiceProxy -Uri $URI -Class SitecorePS -Namespace webservice
$GLOBAL:SpeRemoteUser = $User;
$GLOBAL:SpeRemotePassword = $Password;
}

function Execute-RemoteSitecoreScript {
[CmdletBinding()]
param(

[Parameter(Position=3, Mandatory=$true, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[ScriptBlock]$Command
)
$reply = $GLOBAL:SpeRemoteProxy.ExecuteScriptBlock($GLOBAL:SpeRemoteUser,$GLOBAL:SpeRemotePassword,$Command);
$xmlString = $reply -replace "\n", "" -replace "\r",""
$type = $type = [PSObject].Assembly.GetType("System.Management.Automation.Deserializer")
$ctor = $type.getconstructor("instance,nonpublic", $null, @([xml.xmlreader]), $null)
$sr = new-object System.IO.StringReader $xmlString
$xr = new-object System.Xml.XmlTextReader $sr
$deserializer = $ctor.invoke($xr)
$done = $type.getmethod("Done", [System.Reflection.BindingFlags]"nonpublic,instance")
$xmlstring | Out-File -FilePath C:\temp\result.xml
while (!$done.invoke($deserializer, @()))
{
try {
$type.InvokeMember("Deserialize", "InvokeMethod,NonPublic,Instance", $null, $deserializer, [object[]]@())
} catch [Exception] {
write-warning "Error while de-serializing string: $($error[0])"
break;
}
}
$xr.Close()
$sr.Dispose()
}
----version----
language: en
version: 1
revision: 6e708e22-0c51-4dd0-b2a0-753d67e31411

----field----
field: {25BED78C-4957-4165-998A-CA1B52F67497}
name: __Created
key: __created
content-length: 15

20131117T144733
----field----
field: {8CDC337E-A112-42FB-BBB4-4143751E123F}
name: __Revision
key: __revision
content-length: 36

6e708e22-0c51-4dd0-b2a0-753d67e31411
----field----
field: {D9CF14B1-FA16-4BA6-9288-E8A174D4D522}
name: __Updated
key: __updated
content-length: 34

20131118T135750:635203798701342500
----field----
field: {BADD9CF9-53E0-4D0C-BCC0-2D784C282F6A}
name: __Updated by
key: __updated by
content-length: 14

sitecore\admin
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using System.Xml;

namespace Cognifide.PowerShell.PowerShellIntegrations.Commandlets.Remoting
{
[Cmdlet("ConvertFrom", "CliXml", SupportsShouldProcess = false)]
public class ConvertFromCliXmlCommand : PSCmdlet
{
private MethodInfo method;
private MethodInfo done;
[Parameter(Position = 0, ValueFromPipeline = true, Mandatory = true), AllowNull]
public string InputObject { get; set; }

protected override void ProcessRecord()
{
try
{
var reader = new StringReader(InputObject);
var xmlReader = XmlReader.Create(reader);
Type type = typeof(PSObject).Assembly.GetType("System.Management.Automation.Deserializer");
var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null,
new[] { typeof(XmlReader) }, null);
var deserializer = ctor.Invoke(new object[] { xmlReader });
method = type.GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.NonPublic, null,
new Type[] {}, null);
done = type.GetMethod("Done", BindingFlags.Instance | BindingFlags.NonPublic);
try
{
while (!(bool) done.Invoke(deserializer, new object[] {}))
{
WriteObject(method.Invoke(deserializer, new object[] {}));
}
}
finally
{
xmlReader.Close();
reader.Close();
}
}
catch(Exception ex)
{
WriteWarning("Could not deserialize string. Exception: " + ex.Message);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using System.Xml;

namespace Cognifide.PowerShell.PowerShellIntegrations.Commandlets.Remoting
{
[Cmdlet("ConvertTo", "CliXml", SupportsShouldProcess = false)]
public class ConvertToCliXmlCommand : PSCmdlet
{
private object serializer;
private MethodInfo method;
private MethodInfo done;
private StringBuilder builder;
private XmlWriter xmlWriter;
[Parameter(Position = 0, ValueFromPipeline = true, Mandatory = true), AllowNull]
public PSObject InputObject { get; set; }

protected override void BeginProcessing()
{
builder = new StringBuilder();
var settings = new XmlWriterSettings
{
CloseOutput = true,
Encoding = Encoding.UTF8,
Indent = false,
OmitXmlDeclaration = true,
};
xmlWriter = XmlWriter.Create(builder, settings);
var type = typeof(PSObject).Assembly.GetType("System.Management.Automation.Serializer");
var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null,
new[] {typeof (XmlWriter)}, null);
serializer = ctor.Invoke(new object[] {xmlWriter});
method = type.GetMethod("Serialize", BindingFlags.Instance | BindingFlags.NonPublic, null,
new[] {typeof (object)}, null);
done = type.GetMethod("Done", BindingFlags.Instance | BindingFlags.NonPublic);
}

protected override void ProcessRecord()
{
try
{
method.Invoke(serializer, new object[]{InputObject});
}
catch
{
//"Could not serialize $($object.gettype()): $_"
}
}

protected override void EndProcessing()
{
done.Invoke(serializer, new object[]{});
WriteObject(builder.ToString());
File.WriteAllText(@"C:\temp\serialized.xml", builder.ToString());
xmlWriter.Close();
}
}
}
6 changes: 3 additions & 3 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

[assembly: AssemblyVersion("2.5.1.*")]
[assembly: AssemblyFileVersion("2.5.1.0")]
[assembly: AssemblyInformationalVersion("2.5.1.0")]
[assembly: AssemblyVersion("2.5.2.*")]
[assembly: AssemblyFileVersion("2.5.2.0")]
[assembly: AssemblyInformationalVersion("2.5.2.0")]

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
Expand Down

0 comments on commit 08c2339

Please sign in to comment.