This blog post is a "mashup" of a couple of my previous posts, combining the lessons to create something brand new that I hope you will find useful. First, let's review what we know:
- SAS Enterprise Guide supports a scriptable object model, which allows you to write scripts or programs to automate many aspects of the application without interacting with the application's user interface.
- Windows PowerShell is a powerful scripting environment that is built into most Windows desktops, and can be used to automate almost any aspect of your Windows environment, including the running of SAS applications.
It's not a big leap to realize something that we scripting geeks will find very cool: we can use Windows PowerShell to control SAS Enterprise Guide.
In this example, we'll look at a script that can process one or more project files (.EGP files) and report on what's in them. That's right: there is no need to open SAS Enterprise Guide to peek inside the project. We can write a script that pulls the information out of the project for us.
Here is a copy of the script that you can download. To follow along with the instructions in the rest of this post, you should download/copy the file and name it "eg43ProjectContents.ps1" (drop the TXT extension, which I used to make it safe for download). The example is designed with work with SAS Enterprise Guide 4.3.
To run the script, you must invoke the powershell command or run the script from within a PowerShell console window. (Remember, before you can run PowerShell scripts you must enable your Windows environment to allow it.)
IMPORTANT: Because SAS Enterprise Guide is a 32-bit application, you must run the 32-bit version of PowerShell with this script. See this post for more information about how to locate the 32-bit version even when running on 64-bit Windows.
Here is an example command that will report on a single EGP file:
powershell -command "ls c:\projects\DonorsChoose.egp | c:\Scripts\eg43ProjectContents.ps1"
To report on an entire directory of EGP files, simply change the command to:
powershell -command "ls c:\projects\*.egp | c:\Scripts\eg43ProjectContents.ps1"
Here is a partial example of the output for a particular project. The output is emitted to the console, or STDOUT, but you can easily capture it in a file by redirecting the output.
Examining project: C:\Projects\DonorsChoose.egp Process flows within project: Data Descriptors SASHELP VTABLE ( SAS.EG.Scripting.Data ) SASHELP VCOLUMN ( SAS.EG.Scripting.Data ) Data Description ( SAS.EG.Scripting.Report ) Data Imported from donorschoose-org-1may2011-v1-donations.csv ( SAS.EG.Scripting.Data ) Characterize Data ( SAS.EG.Scripting.Task ) Data Imported from donorschoose-org-1may2011-v1-projects.csv ( SAS.EG.Scripting.Data ) Characterize Data ( SAS.EG.Scripting.Task ) Data Imported from donorschoose-org-1may2011-v1-resources.csv ( SAS.EG.Scripting.Data ) Characterize Data ( SAS.EG.Scripting.Task ) Data Description ( SAS.EG.Scripting.Query ) Column descriptions ( SAS.EG.Scripting.Query ) Link to Data Imported from donorschoose-org-1may2011-v1-donations.csv ( SAS.EG.Scripting.Link ) Link to Data Imported from donorschoose-org-1may2011-v1-projects.csv ( SAS.EG.Scripting.Link ) Link to Data Imported from donorschoose-org-1may2011-v1-resources.csv ( SAS.EG.Scripting.Link ) Link to SASHELP VTABLE ( SAS.EG.Scripting.Link ) Link to SASHELP VCOLUMN ( SAS.EG.Scripting.Link ) About the data Normalized Data Schema ( SAS.EG.Scripting.File ) Data Schema ( SAS.EG.Scripting.File )
You can view the full output for this example here.
The example script contains many code comments to help you to understand what's going on, but here are a few highlights. To "invoke" the SAS Enterprise Guide scripting object, you use PowerShell commands to create a COM object that represents the application:
# Launch the application using the registered prog ID $eguideApp = New-Object -comObject SASEGObjectModel.Application.4.3
To load a project into the application, use the Open() method (which accepts two arguments: a file name and optionally, a password -- for protected project files). Because this script accepts a list of files piped in from the command invocation, the candidate files are stored in the special $input variable:
foreach ($projName in $input) { # Open the project file Write-Host " --------------------------------------------- " Write-Host "Examining project:" $projName $project = $eguideApp.Open("$projName", "") # all other processing for this project # .... # Close the project file $project.Close() }
To iterate through each process flow within a project, use the ContainerCollection property on the Project object. Note that there are different types of top-level "containers" in the object model. The Process Flow is the most common, but there are also containers for Reports, Distribution (such as Send E-mail steps) and Ordered Lists. The Process Flow has a ContainerType of 0.
# Show all of the process flows in the project $pfCollection = $project.ContainerCollection Write-Host "Process flows within project:" foreach ($pf in $pfCollection) { if ($pf.ContainerType -eq 0) { Write-Host " " $pf.Name # To RUN a process flow, simply use $pf.Run() } }
Note: As you review the output from the scripting model, you might notice that the objects are not reported in the same sequence that you expect to find them visually when you view the project in SAS Enterprise Guide. For example, the Process Flow objects are not always reported in the same order that you see them in the project tree. Alas, the SAS Enterprise Guide automation model does not offer a completely accurate representation of the object arrangement in your project and process flows, only the content.
To write your own scripts, you will need the reference documentation for the SAS Enterprise Guide object model. That's available here, in a CHM help file contained within a ZIP file. (Note that this is the version 4.2 documentation, but the object model is the same in 4.3. To view the contents of the CHM file, you may need to "unblock" it within your Windows environment.)
15 Comments
very interesting!
can we automate this within SAS to, say, report whether any (and which) objects use a particular column name within a project?
Peter, good question!
I plan to have one or two more posts on this topic, showing how to dive deeper in the project contents. From there, creative problem solvers like yourself can probably figure something out.
Hi ,
I have about SAS EG projects which I have to script them into *.sas Files.
Can you please tell me if there is easy way to do this. I have to repeat this every week.
Your help inthis regard is highly appreciated.
Thanks
Unfortunately, there is not a way to automate the "Export All Code" feature in scripting language using SAS Enterprise Guide automation.
It is possible to use the scripting language to enumerate all of the task and code items within a project, and then export each one individually (using the SaveAs method for each one). But that does not take into account the sequence of items as shown in the process flow, so it's possible (likely) that the items would be exported out of order.
It would also be possible to create a custom task and use the ISASProject interfaces to automate some of this. There is an example that uses the ISASProject interface here: http://support.sas.com/documentation/onlinedoc/guide/customtasks/. See the "Program Manager" example. Creating a custom task requires .NET programming.
Pingback: My favorite SAS tips and tools from 2012 - The SAS Dummy
Hi,
I don't have much experience with Powershell scripting, however I want to create a script that can use the functionality of formatting script in EG "Ctrl I" is the shortcut. so basically I want to open a sas script format the script using EG and then close. Is there any way you might be able to help me with such a script
Thank you in advance.
Antonie,
There isn't an EG API that you can use for this from PowerShell, but you can probably use a UI automation tool (such as AutoHotKey) to record a UI macro that you can repeat with multiple files.
Hi, I am using powershell to run Enterprise Guide. I noticed that the .egp file which runs opens in read+write mode. How can I restrict it to open only in read-mode? This is how I defined my script now:
$obj = "SASEGObjectModel.Application.5.1"
$pth = "G:\ANALYTICS\SAS_EGP\.egp"
$EGP = new-object -comObject $obj
$EGP.open($pth," ")
$proj = $EGP.Project
$proj.run()
$projname = $proj.Name
$proj.close()
Kate,
The only method is to actually mark the file as READ ONLY in the operating system. Do this either with Windows Explorer (via file properties) or in your script.
Then reset:
Thank you for your help.
I am noticing some sporadic behavior when I run multiple powerscripts at the same time to run different Enterprise Guide projects. I am using the 'Read-Only' mode as you described.
It errors out at new-object : Exception has been thrown by the target of an invocation.
+ $EGP = new-object -comObject $obj
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-Object], TargetInvocation
Exception
+ FullyQualifiedErrorId : System.Reflection.TargetInvocationException,Micr
osoft.PowerShell.Commands.NewObjectCommand
But next time I run the same script is runs fine. And the error is not specific to any particular Enterprise Guide Project.
Any clue? Thanks.
Is it possible that there is contention with a project file that two instances are trying to access at the same time?
I thought so, but shouldn't $file.Attributes = 'ReadOnly' prevent that from happening?
I assigned the egp file to read-only. Other users only have read access too.
I would think so. Perhaps you should try "slowing" down the script with a Start-Sleep call to allow sufficient time for file operations to complete.
Hi - very interesting series of blog posts on Powershell automation so thanks for pulling them together.
I was wondering if it was possible to use this script when the .egp files are held on a SAS server rather on the PC running the script? If it is, how would one do this?
Thanks,
Nick
If these EGP files are stored on the SAS server file system, it's tricky. EG automation does not have a method for opening/running EGP files that are remote.
However, there are some tricks I can think of.
You could create a small project that has just the Copy Files task in it. Use that task to copy the remote EGP files to your local PC. You can automate that project with a script. Then, use the techniques I described here to report on the now-local-version of the EGP file that you copied down.