Powershell and XMLRPC

2.9k views Asked by At

We are a Windows shop using Powershell extensively.We also have a Spacewalk that I would like to poll some data from as part of the existing Powershell script. Spacewalk API is exposed via XMLRPC.

I have spent some time searching for examples on how this can be done but the information is really scarce. The closest I could get was this link ( no longer available) https://web.archive.org/web/20080202045713/http://thepowershellguy.com/blogs/posh/archive/2008/01/31/powershell-and-xmlrpc-posh-challenge-part-12.aspx

Lack of examples makes me think that I am looking in the wrong direction. I know about new-webserviceproxy and I used it for quering Sharepoint but I don't see anyone using it for XMLRPC calls.

It is trivial to write the call in Perl or Python but this is not what I need in this specific case...

Am I going the wrong way here?

2

There are 2 answers

2
Keith Hill On BEST ANSWER

Have you looked at XML-RPC.NET? You would have to create a XmlRpcProxyGen class in C# that implements IXmlRpcProxy but once you've done that, you should be able to load that .NET assembly and use the proxy class from PowerShell.

0
burkasaurusrex On

Just implemented this myself, so I thought I'd pass it along.

You can actually download the DLL instead of compiling the source yourself - I found the DLL by using NuGet, but some say you can get it from the zip.

I decided to implement the interfaces in C# code within powershell to maximize portability / ease of development. If you want, you can compile the C# code as a DLL and load that using powershell, but you'll have to go back and recompile every time you want to make a change to the C# code. Here, powershell recompiles for you on the fly. (The only downside is that if you use the native windows powershell IDE, you have to close and reopen to clear your session every time you make a change to the C# code)

Here's an example of the OpenSubtitles API using XML-RPC.NET and powershell (not the cleanest code, but hopefully illustrates the XML-RPC.net usage):

$source = @'
namespace OpenSubtitlesAPI
{
    using CookComputing.XmlRpc;

    [XmlRpcUrl("http://api.opensubtitles.org/xml-rpc")]
    public interface IOpenSubtitles : IXmlRpcProxy
    {
        [XmlRpcMethod("LogIn")]
        XmlRpcStruct LogIn(string username, string password, string language, string useragent);

        [XmlRpcMethod("LogOut")]
        XmlRpcStruct LogOut(string token);

        [XmlRpcMethod("SearchSubtitles")]
        XmlRpcStruct SearchSubtitles(string token, XmlRpcStruct[] queries);

        [XmlRpcMethod("SearchSubtitles")]
        XmlRpcStruct SearchSubtitles(string token, XmlRpcStruct[] queries, int limit);
    }

    public class ProxyFactory
    {
        public static IOpenSubtitles CreateProxy()
        {
            return XmlRpcProxyGen.Create<IOpenSubtitles>();
        }
    }
}
'@

# Load XML-RPC.NET and custom interfaces
if ([Type]::GetType("OpenSubtitlesAPI.ProxyFactory") -eq $null)
{
    [Reflection.Assembly]::LoadFile("C:\path\to\CookComputing.XmlRpcV2.dll") | Out-Null
    $dynamicAssembly = Add-Type -TypeDefinition $source -ReferencedAssemblies ("C:\path\to\CookComputing.XmlRpcV2.dll")
}

# Set up proxy
$proxy = [OpenSubtitlesAPI.ProxyFactory]::CreateProxy()
$proxy.UserAgent = "user agent"
$proxy.EnableCompression = $true

# Log in
$LogInResponse = $proxy.LogIn("user name", "password", "language", "user agent")

# Build query
$query = New-Object CookComputing.XmlRpc.XmlRpcStruct
$query.Add("moviehash", "movie hash")
$query.Add("moviebytesize", "movie size")
$query.Add("sublanguageid", "language")
$queries = @($query)

# Search
$SearchResponse = $proxy.SearchSubtitles($LogInResponse.token, $queries)

# Log out
$LogOutResponse = $proxy.LogOut($LogInResponse.token)

My response is a bit delayed to the initial question, but hopefully this helps someone out there.