Be sure to check out my Scripting4Crypto initiative. It’s a fun way to get into using cryptocurrencies all while getting your PowerShell needs met.
ProjectWise provides a powerful Saved Search feature, but managing those searches programmatically isn’t always straightforward. While the ProjectWise SDK exposes many useful APIs, some functionality—such as modifying an existing saved search—requires calling native functions from dmscli.dll.
In this post, I’ll walk through a PowerShell solution that allows you to update the name of an existing ProjectWise saved search, using a combination of C# interop and the ProjectWise API.
Why This Is Useful
Renaming saved searches programmatically can be helpful when:
- Standardizing naming conventions
- Migrating environments (DEV → TEST → PROD)
- Updating legacy saved searches
- Automating administrative cleanup tasks
Instead of manually editing saved searches through ProjectWise Explorer, this approach allows you to automate the process.
How It Works (High-Level)
This script performs the following steps:
- Loads a C# class at runtime using
Add-Type - Imports the native ProjectWise API function
aaApi_SQueryModifyfromdmscli.dll - Finds the saved search ID based on its current name
- Calls the API to rename the saved search
Step 1: Import the Required ProjectWise API Function
The aaApi_SQueryModify function is not directly exposed via PowerShell, so we define it using C# and P/Invoke.
try {
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class DMSFunctions
{
[DllImport("dmscli.dll", CharSet = CharSet.Unicode)]
public static extern bool aaApi_SQueryModify (
int lQueryId,
int ulModifyFlags,
string lpctstrName,
string lpctstrDesc,
IntPtr hCriteriaBuf
);
}
"@ -Language CSharp
if ([AppDomain]::CurrentDomain.GetAssemblies().GetTypes().Name -contains "DMSFunctions1") {
Write-Host "DMSFunctions is loaded." -ForegroundColor Green
} else {
throw "DMSFunctions is not loaded."
}
} catch {
Write-Warning -Message $_
}
Key Notes
dmscli.dllmust be available (ProjectWise Explorer installed)ulModifyFlags = 1indicates the name is being modified- We are not modifying the description or criteria buffer in this example
Step 2: Locate the Saved Search and Update Its Name
Once the API is available, we retrieve the saved search ID and apply the update.
try {
$SavedSearchName = 'ImportantDocs'
$SavedSearchName_New = 'ImportantDocs_Updated'
# Get saved search based on the name
if ([int]$pwSavedSearchID = (Get-PWSavedSearches).Select("Name = '$SavedSearchName'") |
Select-Object -ExpandProperty ID) {
Write-Host "$pwSavedSearchID - saved search ID." -ForegroundColor Cyan
} else {
throw "Saved search '$SavedSearchName' not found."
}
if ([DMSFunctions1]::aaApi_SQueryModify(
$pwSavedSearchID,
1,
$SavedSearchName_New,
[string]::Empty,
[IntPtr]::Zero)) {
Write-Host "Successfully updated saved search to '$SavedSearchName_New'." -ForegroundColor Cyan
} else {
throw "Failed to update the saved search."
}
} catch {
Write-Warning -Message $_
}
What Each Parameter Does
| Parameter | Description |
|---|---|
lQueryId |
ID of the saved search |
ulModifyFlags |
1 = modify name |
lpctstrName |
New saved search name |
lpctstrDesc |
Description (unused here) |
hCriteriaBuf |
Criteria buffer (unused here) |
Important Considerations
- The script must run in a ProjectWise-integrated PowerShell session
- The user must have permissions to modify saved searches
- Always test in a non-production environment first
- Saved search names must be unique
Closing Thoughts
This approach demonstrates how PowerShell can be extended beyond standard cmdlets by leveraging native ProjectWise APIs. By combining PowerShell, C#, and dmscli.dll, you can unlock advanced administrative capabilities that aren’t otherwise exposed.
If you’re automating ProjectWise administration, techniques like this can save significant time and reduce manual effort.
Experiment with it and have fun.
Hopefully, you find this useful. Please let me know if you have any questions or comments. If you like this post, please click the Like button at the bottom of the page. And thank you for checking out my blog.
