-
-
Save leftp/881215d56ae97f109039c094e21cea66 to your computer and use it in GitHub Desktop.
code example to copy files through winrm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading; | |
using System.Management.Automation; | |
using System.Management.Automation.Runspaces; | |
using System.Security; | |
namespace WinRM_File_Copy | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var winrm = new WinRMController("remote.host", 5985, "Administrator", "pass"); | |
winrm.CopyLargeFile(@"c:\file1", @"c:\file_copy"); | |
} | |
} | |
public class WinRMController | |
{ | |
private string hostAddress; | |
private string username; | |
private string password; | |
private int winrmPort; | |
private const string ShellSchema = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell"; | |
public WinRMController(string HostAddress, int WinRMPort, string UserName, string Password) | |
{ | |
hostAddress = HostAddress; | |
username = UserName; | |
password = Password; | |
winrmPort = WinRMPort; | |
} | |
public void CopyLargeFile(string sourceFilePath, string destinationFilePath) | |
{ | |
var fs = File.Open(sourceFilePath, FileMode.Open, FileAccess.Read); | |
uploadChunks(fs, destinationFilePath); | |
} | |
private void uploadChunks(FileStream reader, string filePath) | |
{ | |
// Upload the file in chunks to get around the Windows command line size limit. | |
// Base64 encodes each set of three bytes into four bytes. In addition the output | |
// is padded to always be a multiple of four. | |
// | |
// ceil(n / 3) * 4 = m1 - m2 | |
// | |
// where: | |
// n = bytes | |
// m1 = max (8192 character command limit.) | |
// m2 = len(filePath) | |
int chunkSize = ((8000 - filePath.Length) / 4) * 3; | |
byte[] chunk = new byte[chunkSize]; | |
var runspace = OpenRunspace(false); | |
runspace.ThreadOptions = PSThreadOptions.ReuseThread; | |
runspace.ApartmentState = ApartmentState.STA; | |
runspace.Open(); | |
try | |
{ | |
int bytesRead = reader.Read(chunk, 0, chunkSize); | |
while (bytesRead != 0) | |
{ | |
string content = Convert.ToBase64String(chunk.Take(bytesRead).ToArray()); | |
appendContent(runspace, filePath, content); | |
bytesRead = reader.Read(chunk, 0, chunkSize); | |
} | |
} | |
finally | |
{ | |
runspace.Close(); | |
} | |
} | |
private void appendContent(Runspace runspace, string filePath, string content) | |
{ | |
string remoteScript = string.Concat( | |
string.Format("$b='{0}';$d='{1}';\r\n", content, filePath), | |
"$bytes=[Convert]::FromBase64String($b);", | |
"$fs=[IO.File]::Open($d,[IO.FileMode]::Append,[IO.FileAccess]::Write);", | |
"$fs.Write($bytes,0,$bytes.Length);", | |
"$fs.Flush();$fs.Dispose();" | |
); | |
var powershell = PowerShell.Create(); | |
powershell.Runspace = runspace; | |
powershell.AddScript(remoteScript); | |
var results = powershell.Invoke(); | |
if (powershell.HadErrors) | |
{ | |
StringBuilder stringBuilder = new StringBuilder(); | |
foreach (var errorRecord in powershell.Streams.Error) | |
{ | |
stringBuilder.AppendLine(errorRecord.ToString()); | |
} | |
Console.Write(stringBuilder.ToString()); | |
throw new Exception("Error occured during file copy."); | |
} | |
powershell.Dispose(); | |
} | |
private Runspace OpenRunspace(bool opened = true) | |
{ | |
Runspace remoteRunspace = null; | |
getRunspace( | |
string.Format("https://{0}/wsman", hostAddress), | |
winrmPort, | |
ShellSchema, | |
username, | |
password, | |
ref remoteRunspace | |
); | |
if (opened) | |
remoteRunspace.Open(); | |
return remoteRunspace; | |
} | |
private static void getRunspace(string uri, int port, string schema, string username, string livePass, ref Runspace remoteRunspace) | |
{ | |
SecureString password = new SecureString(); | |
livePass.ToCharArray().ToList().ForEach(p => password.AppendChar(p)); | |
PSCredential psc = new PSCredential(username, password); | |
WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc); | |
rri.AuthenticationMechanism = AuthenticationMechanism.Basic; | |
rri.Port = port; | |
rri.ProxyAuthentication = AuthenticationMechanism.Negotiate; | |
rri.SkipCACheck = true; | |
rri.SkipCNCheck = true; | |
rri.SkipRevocationCheck = true; | |
remoteRunspace = RunspaceFactory.CreateRunspace(rri); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment