Video Screencast Help

SVS 2.X SDK Guide Part 5: Create, Capture & Data

Created: 05 May 2008 • Updated: 29 Jul 2010 | 1 comment
Language Translations
Jordan's picture
0 0 Votes
Login to vote

Being able to capture applications or updates in a layer is the Holy Grail of the SVS SDK and, well, the reason people use SVS. Surprisingly, creating and capturing layers is one of the simplest things to do with the SDK, especially when compared to Export and Import. With the information presented in this article you should easily be able to implement these SVS features into any tool you're making.

Changes to FLS2 Class

Several new methods have been marshaled in ManagedSVS.cs

A few new Constants have also been added.

You can download the newest version of the FSL2 Class from the download portal.

Creating an Empty layer

Before you can capture anything into a layer you need to create the layer first. When you capture in SVSadmin or SVScmd those tools automatically create an empty layer before starting the capture (unless you're updating an existing layer).

FSL2CreateLayer

public static extern UInt32 createLayer
 (
  string fslName,
  UInt32 layerType,
  bool createPeer,
  [MarshalAs(UnmanagedType.LPStr, SizeConst = MAXIDLEN)] StringBuilder importedGuid
 );

By now the information in CreateLayer should be familiar to you. It's quite similar to several of the Common Methods I covered in Part 2. You pass in the layer name, the layer type and whether or not you should create the peer and it returns ImportedGuid. Layer types are the same as the attributes we covered last time: Normal (0), Peer (1) or Data (2). There are constants for each of these, LAYER_TYPE_NORMAL and so fourth. If you don't want to remember the numerical values, Normal is Read only while Peer is Write only. If you want to add a write layer to a normal, pass in a True for createPeer.

Capturing and Updating

There are three ways in SVS to capture an application. Global and single are the two everyone is familiar with but you can also do a third type which is sort of a mix of the two. Global just starts capturing all changes and you can stop it at any time. Single capture is handed an EXE path and it will capture that process until it's done and then SVS will end the capture when said process is done. The third type of capture uses a PID like single capture but allows you to end the capture whenever you want and it won't auto terminate the capture once the process is done. Also since it takes a PID and not an EXE path you can make it so the process you want to capture is already running which you cannot do with either SVSadmin or SVScmd.

Updating a layer, or placing something into the read only layer of an existing layer, is actually just placing a layer back into capture mode using the same functions you'd use to originally capture the application so in reality the only difference between "capture" and "update" is with update the layer isn't empty. It's a difference of terminology but not of function.

CaptureByPIDWithWait

Or CaptureByPID in the FLS2 class (I hate long names) is the method that's called to do a single process/program capture in SVS.

public static extern UInt32 captureByPID
 (
  string fslGUID,
  string exePath,
  string parameters
 );
 

CaptureByPid takes three strings, the GUID of an existing layer -- either one just created or an older layer -- the path to the exe, msi or whatever you want to capture, and lastly, any parameters you want to pass in. So basically, all the stuff you see in the GUI when creating a new single capture layer. You'll notice that you're actually not passing in a PID to this function, but you can in a different one that doesn't have PID in the function name. This can get confusing.

Start Capture

Start capture is part one of two functions needed to do Global capture and our recently mentioned capture type 3.

public static extern UInt32 startCapture
 (
  string fslGUID,
  bool bTrack,
  UInt32 dPid,
  bool bRunAppsInStartupFolder
 );

Like CaptureByPID, StarCapture takes an existing Guid but the rest is unique to this method. bTrack is a bool that tells SVS that we want to track a specific process when in capture mode. This is how you start capture type 3, and then dPid is the PID you want to track. You'll notice that it's an integer so you cannot pass in an EXE path like with CaptureByPid, so it gets confusing because of some poorly named functions. Lastly is bRunAppsInStartupFolder, this is something we've seen before with Activate in the SDK and if you pass in true the apps in the startup folder will launch upon capture.

End Capture

public static extern UInt32 endCapture
 (
  string fslGUID
 );
 

End capture takes a GUID that's in capture mode and then ends that capture. Pretty straight forward.

Query Capture

public static extern bool queryCapture();

QueryCapture checks to see if SVS is in capture mode and is one of the few methods that returns a Boolean instead of zero for success or an error code. There's nothing to pass in because only one layer can be in capture mode at a time.

Data Layers

In addition to application layers you have Data Layers in SVS, they're created with the same CreateLayer function but do not have a peer and have their own rules. In the SDK there are two Data Layer specific methods available.

FSL2EnumDataLayerItem

public static extern UInt32 enumDataLayerItem
 (
  string fslGUID,
  UInt32 index,
  [MarshalAs(UnmanagedType.LPStr)] StringBuilder dataPatternBuffer,
  ref UInt32 dataPatternBufferLen,
  ref UInt32 dataType
 );

The first function allows you to enumerate through all the data layer capture items, you need to pass in an index which you have to increment yourself and the method returns 0 on success and 1041 as the error (layer not found) when there are no more items to enumerate. The method returns a buffer with the name of the capture item and the type which are as follows (the constant value is in parenthesis):

  • 0 for file extension (FSL2_DATA_LAYER_CAPTURE_EXT)
  • 1 for Directory (FSL2_DATA_LAYER_CAPTURE_DIR)
  • 2 for Directory and subdirectory (FSL2_DATA_LAYER_CAPTURE_DIR_AND_SUBDIR)

Note: For C# I've found this method to be very finicky and not work in many instances. There's something about the function -- or how it's being called -- that .Net doesn't like and there are times where a data layer item will not be found or returned truncated. However it's very easy to get the data layer capture items out of the registry. They're under the "Data Layer" Key for the Read Only layer of your data layer and are of type REG_DWORD. Using the information in Part Four and some simple .Net code you can write a function to enumerate these items much quicker than it would be to try and deal with FSL2EnumDataLayerItem.

Here's the code (this isn't in the FSL2 Class):

public static void GetDataLayerItems(string myGuid, FSL2 mySVS) 
 {
   mySVS.pInfo.dwStructSize = (UInt32) Marshal.SizeOf(mySVS.pInfo);
   UInt32 result = FSL2.getLayerInfo(myGuid, mySVS.pInfo);
   string mySubKey = mySVS.pInfo.regPath;
   RegistryKey myKey = Registry.LocalMachine.OpenSubKey(mySubKey, true).OpenSubKey("DataLayer", true);
   foreach (string subKeyName in myKey.GetValueNames()) {
    Console.WriteLine("Exclude Name: " + subKeyName + " value: " + myKey.GetValue(subKeyName).ToString());
   }
 }
 

FSL2SetDataLayerItem

public static extern UInt32 setDataLayerItem
 (
  string fslGUID,
  string dataPattern,
  int dataType
 );
 

Setting and removing datalayer capture items is very simple, you pass in a GUID, a value and the type (which are the same mentioned in the previous section). If you pass in a -1 for the type (SL2_DATA_LAYER_NONE is the constant) then that item will get deleted from the data layer list.

When passing in a directory, this function will not automatically format the path to use the variable system that SVS has. An example of this is C:\Test won't get translated into [SystemDrive]\Test. There is a way to get SVS to do this for you, but it requires multiple steps which there isn't space for in this article so you may want to write your own function to do this.

Seeing it in Action

To show how this all works I'm going to have two functions here, one that creates and empty layer and captures an program via it's installer and one that creates a data layer and adds items to it for capture.

public static void captureProgram(string myName, string myPath,string myArgs) {
      StringBuilder myGuid = new StringBuilder(FSL2.MAXIDLEN);
      UInt32 result = FSL2.createLayer("onPreCreateGlobal", FSL2.LAYER_TYPE_NORMAL, true, myGuid);
      if (result == 0) {
        result = FSL2.CaptureByPID(myGuid.ToString(), myPath, myArgs);
        if (result) {
          Console.WriteLine("capture complete");
        } else {
          Console.WriteLine("Error during capture");
        }
      } else {
        Console.WriteLine("Error");
      }
    }

In the first function we're passing in a layer name, the path to the app exe and any args you want to use. It really is that simple to capture a new application in SVS using the SDK.

public static void CreateDataLayer(string myName,string[] captureItems) {
      StringBuilder myGuid = new StringBuilder(FSL2.MAXIDLEN);
      UInt32 result = FSL2.createLayer(myName, FSL2.LAYER_TYPE_DATA, true, myGuid);
      if (result == 0) {
        foreach (string myItem in captureItems) {
          result = FSL2.setDataLayerItem(myGuid.ToString(), myItem, FSL2.FSL2_DATA_LAYER_CAPTURE_EXT);
        }
        
      } else {
        Console.WriteLine("Error");
      }

    }

The second function takes a name and a collection of strings and then creates a data layer and adds each item in the captureItems collection to the data layer's capture list. Now this is only adding them as file extensions. You'd have to expand the function by passing in a custom collection to be able to do more then just that, but for the sake of example this works just fine.

Conclusion

Capture with the SDK is very simple. With the exception of the data layer enumeration problem, the methods covered in this article are probably some of the simplest to implement that I've written about so far. Being able to make a data layer tool is something people ask about regularly since there's no way to create and manage them in SVScmd, and with the information I covered anyone should easily be able to make such a tool. OnEvents and Excludes are on deck for the next article.

Remember that future versions will be listed in the FSL2 Class Portal where the FSL2 class is available for download. Be sure to subscribe to that thread which will inform you of any new articles and updates to the class.

Return to the Virtualization SDK Book

Comments 1 CommentJump to latest comment

dannyw's picture

Hi,

I have recently started working on an existing project using SVS SDK. We have some portion of code which does the global program capture.

It looks something like this.

 private void StartCapture(string guid)
        {
            UInt32 result = FSL2.startCapture(guid, false, 0, false);
            if (result != FSL2.ERROR_SUCCESS)
            {
                throw new AppPackagingException(AppPackagingException.ErrorReason.UnableToStartCapture,
                    "Error starting application capture: " + result, result);
            }

            // Remember the guid of the layer that will be in capturing state
            this.SaveCaptureLayerGuid(guid);

        }

 

The question is how I can use the function FSL2.startCapture() to do single program capture. How can I pass in the executable filename and its parameters?

I tried to look up the FSLLIB.HLP, but it is really too brief.

thanks

danny

0
Login to vote