Welcome to the new Box Support website. Check out all the details here on what’s changed.

Automating box processes using powershell and the box windows sdk

New post

Comments

10 comments

  • whiggs12

    Oh, and one more thing.  I also used ILSpy to decompile the box windows sdk dll file, which was infinitely helpful in figuring out what all of usable commands are and what their arguments are.

    0
    Comment actions Permalink
  • whiggs12

    I wanted to add one more piece of information.  Thanks to the help of mattwiller on Github, I now finally understand why, when running the windows sdk in powershell, 2 different versions of the Newtonsoft.Json assembly were required (version 9.0.0 and 10.0.3):

     

    It looks like this works in full .NET applications but not in PowerShell because the SDK's app.config file that binds any version of Newtonsoft.Json to the 10.x version that the SDK installs is not being loaded by PowerShell. Fundamentally, since you're going outside of the SDK's normal operation and loading the assemblies manually, you're going to have to ensure that the correct versions are installed and referenced. In the course of our investigation we found some information about how to make PowerShell load the app.config, but weren't able to make it work in our environment. 

     

    The app.config file that mattwiller references is located here, and it is a bit difficult to implement if you are running a straight powershell script.  Allow me to explain: when you run an executable, if there is a ".config" file in the same directory as the executable and has the same name (eg. "aprocess.exe" would have a config file named "aprocess.exe.config"), the executable (from my understanding) is able to pull settings from this config file for use when the script is run.  I did some research into the link that mattwiller posted, but was not able to successfully load the app.config file into the powershell script.  Then, it struck me: the answer was not to load an app.config file into the powershell session, as powershell is itself, a process, and has its own config file located in the same directory that the powershell executable is located (C:\Windows\System32\WindowsPowerShell\v1.0).  So, due to the fact that the powershell executable is run whenever a script is run on the machine, one would have to modify the powershell.exe.config (and/or powershellise.exe.config) files and add the content of the app.config file linked above in order to get powershell to correctly load the Newtonsoft.json.10.0.3 assembly.  If, however, you are like me and don't want to necessarily modify system files like that, good news is that that is not the only option.  The second option, however, involves converting the powershell script into an executable file and then creating a config file for that executable.  If you use Sapien powershell studio, when you build a package, by default, the config file is created along with the executable, so all you would have to do is add the contents of the app.config file linked above to the newly created config file for the executable powershell studio generated, and presto, works like a charm.  Below is what an example config file would look like:

     
     
      
        
          
            
            
          
        
      
         
                
    	    
         
    	
    		
    	
    

    For those who do not have powershell studio and is outside your price range, don't worry, you can still perform this process, although you will have to do it all manually.  There is a cool little application called ps1 to exe converter (both a portable and web based) which will convert a powershell script into an executable, and includes other really cool features, like embedding files, choosing the working directory, etc.  You can use this tool to convert the powershell script to an executable, then create the config file for the executable, modify it with the contents of the app.config file linked above, (optionally) embed it within your converted executable, and you are good to go.

    0
    Comment actions Permalink
  • BentheBuilder

    I'm getting the following error when attempting to get the AdminToken. And suggestions on why? 

     

    The value of $boxJWT is :

    Box.V2.JWTAuth.BoxJWTAuth

     

    $tokenreal = $boxJWT.AdminToken()
    Exception calling "AdminToken" with "0" argument(s): "The type initializer for
    'System.IdentityModel.Tokens.Jwt.JsonExtensions' threw an exception."
    At line:1 char:1
    + $tokenreal = $boxJWT.AdminToken()
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : TypeInitializationException

    0
    Comment actions Permalink
  • mwiller

     This is likely because the exact issue that  describes in his post above — the Box SDK depends on Newtonsoft.Json 10 but the System.IdentityModel.Tokens.Jwt library we use depends on 9.  A full .NET project respects the SDK's app.config file that does a binding redirect to reconcile these dependencies, but if you're loading assemblies manually in PowerShell you're probably not picking that config up and the IdentityModel library is not able to resolve it's dependency on Newtonsoft.Json 9.  In the post above,  gives some helpful information to fix that issue — could you try that out and see if it works for you?

    0
    Comment actions Permalink
  • whiggs12

    To piggy back off what  said, you might find the below code snippet very useful, as it allows you to perform powershell binding redirection:

    # Load your target version of the assembly
    $newtonsoft = [System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll")
    $onAssemblyResolveEventHandler = [System.ResolveEventHandler] {
      param($sender, $e)
      # You can make this condition more or less version specific as suits your requirements
      if ($e.Name.StartsWith("Newtonsoft.Json")) {
        return $newtonsoft
      }
      foreach($assembly in [System.AppDomain]::CurrentDomain.GetAssemblies()) {
        if ($assembly.FullName -eq $e.Name) {
          return $assembly
        }
      }
      return $null
    }
    [System.AppDomain]::CurrentDomain.add_AssemblyResolve($onAssemblyResolveEventHandler)
    
    # Rest of your script....
    
    # Detach the event handler (not detaching can lead to stack overflow issues when closing PS)
    [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($onAssemblyResolveEventHandler)
    0
    Comment actions Permalink
  • Garv

    Hi, I want to know whether we can automate file access process on the box from this code or not? 

    I am in an internship where I have to automate some process which includes a step where we have to give access of some files to selected users. So, can I use this code to automate file access process?  If not then, please tell me any other possible way  

    0
    Comment actions Permalink
  • whiggs2

    .  If you are still looking for an answer to this question, the answer is yes.  If you open the box windows sdk solution in visual studio and navigate to the collectionsmanager, you will see several methods to manipulate collaborations.

    0
    Comment actions Permalink
  • gfish1

    For those of you who are interested, I have created a full powershell module which acts as a wrapper for the box windows sdk, removing the need for you to directly work with the sdk.  To install the module, make sure you have powershellget installed and run

    Install-module Poshbox -force -allowclobber

    You can view the source code for the module here.  You can also submit any issues that you encounter or contribute yourself.

    0
    Comment actions Permalink
  • mboggs

    ,Your link doesn't seem to function anymore. Are you still maintaining "PoshBox" and if so, where can I get more info?

    0
    Comment actions Permalink
  • whiggs

    Poshbox powershell module can be found here .  You can also install poshbox using powershellget:

     

    Install-module poshbox

    0
    Comment actions Permalink

Please sign in to leave a comment.