Tag Archives: C#

VS Binary Module Tip: PowerShell 5.0 SDK Reference Assemblies – Nuget

PowerShell 5.0 SDK Reference Assemblies is available in NuGet. If you are building binary modules you can add the references from Visual Studio just by executing the below command in NPM Console

Install-Package Microsoft.PowerShell.5.ReferenceAssemblies -Verbose

In the NPM UI we can get it in one go – By Clicking Install
1
Cool, its easy to add the reference to our project and start building the binary module easily. When we build cmdlet we need to run and test the functionality and each time we execute it’s necessary to close the PowerShell Console Host or ISE host if the binary module is loaded and we can’t rebuild the solution. It will end up in Dll in use error. We can easily over come this by following the below steps.

  • Right Click the Solution from Solution Explorer.
  • Choose Properties and in the Right Pane Select Debug
  • Click Select External Program. Navigate to “C:\Windows\System32\WindowsPowerShell\v1.0\”.
  • Select PowerShell.exe
  • Select the option Enable native code debugging

3
So after building the code simple click “Start” in Visual Studio which open the PowerShell Console.
Additionally, we can load our module with the help of Command line arguments.

-NoExit -Command "Import-Module .\PowerShellDemo.dll"

4
Enjoy PowerShell 🙂 🙂 🙂

PowerShell Tip: Extract Images from DOCX File

Summary

It’s an immense pleasure to explore $objects! We do IT Automation tasks using C# or PowerShell. It depends on the requirement and business needs. Recently our team was engaged to extract images from the DOCX files. It’s possible by simply renaming it to ZIP and extract to get the images folder which is not optimal solution at our client environment. So, we used OPEN XML SDK 2.5 (Supported for Office 2016) to accomplish the task.

Requirement

Extract all the images from the given DOCX File. Example Get-Image -FilePath “C:\Temp\Document.Docx”

Solution

  • OPEN XML SDK 2.5
  • Windows PowerShell
  • Visual Studio 2015 (C# Class Library – Binary Module)
  • PowerShell Code

    #using namespace DocumentFormat.OpenXml;            
    [void][System.Reflection.Assembly]::LoadWithPartialName('DocumentFormat.OpenXML')            
    Function Get-Image            
    {            
        Param            
        (            
            [Parameter(Mandatory,            
                       ValueFromPipeline=$true,            
                       ValueFromPipelineByPropertyName=$true,            
                       Position=0,            
                       HelpMessage="Please Enter the Full Path")]            
            [string]            
            $FullName            
        )            
        Process            
        {            
            $Document = [DocumentFormat.OpenXml.Packaging.WordprocessingDocument]::Open($FullName,$false)            
            foreach($Image in $Document.MainDocumentPart.ImageParts)            
            {            
                 [uri]$Uri = $Image.Uri            
                 $ImageFileName = $Uri.ToString().Split("/").Where({$_},'Last',1)            
                 [System.IO.Stream]$Stream = $Document.Package.GetPart($Uri).GetStream()            
                 [System.Drawing.Bitmap]$BitMap = [System.Drawing.Bitmap]::new($Stream)            
                 $BitMap.Save("C:\Temp\Images\" + $ImageFileName)            
            }            
        }            
                   
    }            
                
    Get-Item 'C:\Temp\Demo.Docx' | Get-Image

    Cool, here is the C# Binary cmdlet code to do the same

    [Cmdlet(VerbsCommon.Get,"Image")]
    public class GetImage : Cmdlet
    {
        [Parameter(Mandatory = true,
                   Position = 0)]
        public string FilePath;
        protected override void ProcessRecord()
        {
            //base.ProcessRecord();
            FileStream filestream = System.IO.File.OpenRead(FilePath);
            FileInfo fileinfo = new FileInfo(FilePath);
            WordprocessingDocument document = WordprocessingDocument.Open(filestream, false);
            var images = document.MainDocumentPart.ImageParts;
            foreach(ImagePart image in images)
            {
                Uri uri = image.Uri;
                string mainimage = uri.ToString().Split('/').Last();
                Stream imgstream = document.Package.GetPart(uri).GetStream();
                Bitmap bitmapImg = new Bitmap(imgstream);
                bitmapImg.Save(@"C:\Temp\" + mainimage);
            }
        }
    }

    Conclusion

    We prefer to pick a tool which costs less to deliver the solution. So, at my client place we opted for PowerShell to achieve few automation task with respect to Data Manipulation. To loop through multiple files just used the below snippet:

    Get-ChildItem 'C:\Temp\ProjectFolder\' | Get-Image

    Enjoy PowerShell!

    Note: You can modify the filename of the image as required. In our case it needs to be the same because its customized.

    Tip: Create New List in SharePoint Online Using Exception Handling Scope and Set Properties | PowerShell | CSOM

    Summary

    While presenting about SharePoint Online Client Side Object Model a question popped up “Hey! How can I create a new list if it’s not exist and change properties if exists?”. Not a difficult one. However, we need to build codes with best practise suggested by Microsoft. In short answer is available here.

    Requirement

    • Create a List if it’s not existing.
    • Change Properties if it exists.
    • Allow to create multiple lists in one run
    • Allow users to choose the list template.

    Solution

    Build a binary cmdlet using C# and meet your needs by parameterizing the code. Look at the code below.

    using System;
    using System.Management.Automation;
    using Microsoft.SharePoint.Client;
    namespace xSharePointOnline
    {
        [Cmdlet(VerbsCommon.New, "SPOList")]
        public class NewSPOList : PSCmdlet
        {
            [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
            public Uri SPOurl;
     
            [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true)]
            public string SPOListName;
     
            [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
            public ListTemplateType SPOListTemplateType;
     
            [Parameter(Mandatory = true)]
            [Credential]
            public PSCredential SPOCredential;
     
            protected override void ProcessRecord()
            {
                base.ProcessRecord();
                using (ClientContext SPOClientContext = new ClientContext(SPOurl))
                {
                    SPOClientContext.Credentials = new SharePointOnlineCredentials(SPOCredential.UserName, SPOCredential.Password);
                    ExceptionHandlingScope Scope = new ExceptionHandlingScope(SPOClientContext);
                    using (Scope.StartScope())
                    {
                        using (Scope.StartTry())
                        {
                            List oList = SPOClientContext.Web.Lists.GetByTitle(SPOListName);
                            oList.Update();
                        }
                        using (Scope.StartCatch())
                        {
                            ListCreationInformation oListInformation = new ListCreationInformation();
                            oListInformation.Title = SPOListName;
                            oListInformation.TemplateType = (int)SPOListTemplateType;
                            List oList = SPOClientContext.Web.Lists.Add(oListInformation);
                        }
                        using (Scope.StartFinally())
                        {
                            List oList = SPOClientContext.Web.Lists.GetByTitle(SPOListName);
                            oList.Hidden = true;
                            oList.Description = "PowerShell Rocks!";
                        }
                    }
                    SPOClientContext.ExecuteQuery();
                }
            }
        }
    }

    How to use it?

    • Create a C# Class Library
    • Copy and paste the code. If required change the parameters as required.
    • Build it to get the DLL (Binary)
    • Using Import-Module load the binary DLL E.G. Import-Module C:\Location\Solution.DLL
    • Run the cmdlet New-SPOList -SPOUrl -SPOListName -SPOListTemplateType -SPOCredential

    Here the SPOListTemplate populate the enum values of List Template – So, we can choose the one we need by tab completion

    How it works?

    We have used Exception handling scope which makes one call to the server and that means a lot of performance improvement. All three Try, catch and finally executes at one time.
    Try
    This code simply checks the existence of the list and if exists it will update the hidden and description properties.
    Catch
    If try catch throws exception it will create a new list – If in case of the list not existing.
    Finally
    Update the lists properties.

    Screen Shot

    2746.123

    Converting JSON Time Format in SharePoint Document Library Metadata


    The SharePoint farm has a Document Library and a List which are linked for some requirements, while querying information we received some data which are not in proper format. Challenge is to split, remove characters and count the total which is little tedious

    Example- The Field3 in CSV yields [“\/Date(1444995273796)\/”,”\/Date(1444996968515)\/”]

    It’s a JSON format and the time format is EPOCH (UNIX format) – With Reference to the link MSDN My advice to customer was to use below code snippet to break the mystery!

    To get the count: (Unfortunately, this is what customer need!) – No Fun in it because this kills the actual flavor of SharePoint development and data.

    (@"
    ["\/Date(1444995273796)\/","\/Date(1444996968515)\/"]
    "@ | ConvertFrom-Json).Count
    
    #Output
    #2

    The reason for the SPContext Code by developer is unknown. So here comes the ConvertFrom-JSON power in Windows PowerShell Version 3+ 🙂 🙂 🙂

    To get the information about the data in JSON: [We will deep dive in Part 2 of this Blog]

    @"
    ["\/Date(1444995273796)\/","\/Date(1444996968515)\/"]
    "@ | ConvertFrom-Json
    
    #Output
    
    #Friday, October 16, 2015 11:34:33 AM
    #Friday, October 16, 2015 12:02:48 PM

    The file which is generated as report is done using C# and CSOM – So, in next blog post (Part 2) we will cover Binary Module using C# Class Library, PowerShell Module, String Manipulation and Data consolidation.

    Enjoy PowerShell !