pickle
pickle

Reputation: 43

Converting another language to powershell or using the language in powershell

I have found this code

// "url" is the full destination path (including filename, i.e. https://mysite.sharepoint.com/Documents/Test.txt) 

// "cookie" is the CookieContainer generated from Wichtor's code 
// "data" is the byte array containing the files contents (used a FileStream to load) 

System.Net.ServicePointManager.Expect100Continue = false; 
HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; 
request.Method = "PUT"; 
request.Accept = "*/*"; 
request.ContentType = "multipart/form-data; charset=utf-8"; 
request.CookieContainer = cookie; request.AllowAutoRedirect = false; 
request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; 
request.Headers.Add("Accept-Language", "en-us"); 
request.Headers.Add("Translate", "F"); request.Headers.Add("Cache-Control", "no-cache"); request.ContentLength = data.Length; 

using (Stream req = request.GetRequestStream()) 
{ req.Write(data, 0, data.Length); } 

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
Stream res = response.GetResponseStream(); 
StreamReader rdr = new StreamReader(res); 
string rawResponse = rdr.ReadToEnd(); 
response.Close();
rdr.Close();

Which apparently successfully uploads a large file to a sharepoint site, however my code is in powershell. Is there anyway to use this in powershell in its form now or even convert this to powershell?

Upvotes: 3

Views: 1573

Answers (2)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174545

C# code is, as a general rule, easily translated to PowerShell because C# uses the exact same underlying type system and runtime environment as PowerShell (.NET).

A few things to watch out for:

Variable assignment

C# is a type-safe language, meaning that the compiler guarantees the type of a variable and its value, as seen in your example:

HttpWebRequest request = HttpWebRequest.Create(url); 
//     ^          ^      \________________________/^      
//     |          |                  |             |
//     |    variable name            |    statement terminator ";"
// type-name                         |
//                    static method call that returns a 
//                     value we can assign to "request"

In PowerShell:

  1. Types are implicit, variables are not bound to a single type (thus no need for a type name)
  2. Variable references are prefixed with $
  3. To access static members (like the Create() method above), we use the following syntax:
    • [Namespace.TypeName]::Member
  4. The ; is unnecessary, a linebreak after a statement implies termination

Thus, the above statement becomes:

$request = [System.Net.HttpWebRequest]::Create($url)

Booleans

The two C# boolean keywords (true and false) are, in PowerShell, represented by two automatic variables called $true and $false:

[System.Net.ServicePointManager]::Expect100Continue = $false

using

PowerShell doesn't have a construct comparable to C#'s using statement. To ensure disposal of an object that implements IDisposable, you'll have to use try/catch/finally:

$req = $request.GetRequestStream()
try{
    $req.Write($data, 0, $data.Length)
} catch {
    throw $_
} finally {
    if($req){
        $req.Dispose()
    }
}

Constructors

PowerShell doesn't have a new keyword for object instantiation, but provides the New-Object cmdlet that can wrap C# constructors:

$rdr = New-Object -TypeName System.IO.StreamReader -ArgumentList $res

Rather than:

StreamReader rdr = new StreamReader(res); 

In PowerShell 5.0 and newer, you can now invoke constructors using the new static method as well:

$rdr = [System.IO.StreamReader]::new($res)

Type casting

PowerShell supports both explicit casting that in C# would look like (typename)variable, but again, with square brackets instead of parentheses:

[System.Net.HttpWebResponse]$request.GetResponse()

And (as of version 3.0) it supports unchecked casting as well (still with square brackets):

$request.GetResponse() -as [System.Net.HttpWebResponse]

The latter will return $null, rather than throw an error, if the cast is not possible.


This should get you translating in no time. From the comments in your codefind, it seems you might need to translate "Wichtor's code" as well, in order to generate the $cookie container.

Upvotes: 18

Jower
Jower

Reputation: 575

See below example. I had to wrap the code in class and function.

$code = @"
using System.Security.Policy;
using System.IO;
using System.Net;
public class MySharepointTools 
{
    public void UploadFile(System.String url, System.Net.CookieContainer cookie, System.Byte[] data)
    {
        System.Net.ServicePointManager.Expect100Continue = false; 
        HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; 
        request.Method = "PUT"; 
        request.Accept = "*/*"; 
        request.ContentType = "multipart/form-data; charset=utf-8"; 
        request.CookieContainer = cookie; request.AllowAutoRedirect = false; 
        request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; 
        request.Headers.Add("Accept-Language", "en-us"); 
        request.Headers.Add("Translate", "F"); request.Headers.Add("Cache-Control", "no-cache"); request.ContentLength = data.Length; 

        using (Stream req = request.GetRequestStream()) 
        { req.Write(data, 0, data.Length); } 

        HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
        Stream res = response.GetResponseStream(); 
        StreamReader rdr = new StreamReader(res); 
        string rawResponse = rdr.ReadToEnd(); 
        response.Close();
        rdr.Close();
    }
}
"@

Add-Type -TypeDefinition $code -Language CSharp 

$tools = New-Object MySharepointTools

Now you can call the method using

$Tools.UploadFile(url, cookie, data)

Upvotes: 2

Related Questions