Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

OneIM Extension Example

News

I have changed the main branch to use SDK style project files to allow building DLLs for 9.3+, which switched to .NET. By selecting the target framework dynamically, building for older versions with .NET Framework is also possible. I cut this at 9.0 LTS due to lack of older databases in the lab. For earlier versions I suggest to use the net-framework-legacy branch, that used to work in the past. ;)

I have not tested the new project files for all the listed versions, but it worked for 9.0 and 9.3 and building (without testing the DLLs) was also possible for 9.1.3 and 9.2.1.

With .NET, using the AssemblyResolve event for customizer and authenticator modules no longer appears to work the same way. Instead, I provided an Initialize() method that copies anticipated relevant assemblies (no guarantee I've caught every possible use case) to the executing assembly's directory for .NET and sets the AssemblyResolve event for .NET framework. This might receive more testing later.

What is this?

This is a show case Visual Studio project that demonstrates:

  • Extension of OneIM API
  • Extension of Typed Wrappers
  • Usage of MSBuild stuff to compile against different OneIM versions from the same project directory

The resulting DLLs can also be used in e.g. csharprepl or LinqPad with few dependencies to quickly create a OneIM session.

Why?

Occasionally, I have to demonstrate how to extend OneIM with a DLL against my lab installations. I grew tired of copying the directory everytime I install a new OneIM version in my lab. Now I just have to add a new configuration and build.

Also, when I demonstrate this, I can provide the link to this repository, so there's that. ;)

Usage

Visual Studio

  • Before opening the project, copy localsettings.props.template to localsettings.props.
  • Edit localsettings.props
    • Please note, commit e1716568722b78e821af7706a5c2457222708c31 removed the need to specify an explicit PreprocessorVersion per OneIM version.
  • For each version you would like to build against:
    • provide an installation directory (<OneIMBaseDir>). This ensures that VI.DB and VI.Base are found at compile time and further dependencies (customizers, authenticator) can be resolved at runtime
    • provide an assembly suffix as observed in table DialogScriptAssembly (<AssemblySuffix>). This ensures that TypedWrappers_<AssemblySuffix>.dll is found at compile time
    • optional: provide a default connection string for use in the ExtensionTester or method Utils.GetDefaultOneIMSession
  • OneIM 9.3+:
    • run DbCompiler for the given OneIM version so the global package dir (%USERPROFILE%\.nuget\packages) contains OneIM's NuGet packages
    • run dotnet restore /p:Configuration=<Version>, e.g. dotnet restore /p:Configuration=OneIM931
  • optional: Set ExtensionTester as start project for the solution
  • you can use build.bat where you can build a configuration (e.g. OneIM911) without opening Visual Studio. Using MSBuild requires msbuild.cfg, copy one from "msbuild.cfg examples". Dotnet build is also possible.

GeneratedExtensionSettings.cs in project OneIMExtensions is created by MSBuild before compiling. Therefore it is initially missing, and upon switching configurations, does not contain the correct directory and connectionstring until building.

Anticipated questions

How do I use this in OneIM?

Yes, that was the main use case in the first place, wasn't it? I figured I had to add some lines here.

before 9.3

Copy TypedWrapperExtensions.dll and OneIMExtensions.dll from build directory to frontend directory. For a deployment scenario, you'd add them to the database via SoftwareLoader, but that's outside of the scope of this project. Here's a working example showcasing both DLLs:

#If Not Scriptdebugger
References OneIMExtensions.dll
References TypedWrapperExtensions.dll
Imports OneIMExtensions
Imports TypedWrapperExtensions
#End If

Public Sub CCC_FireEvent (objKey As String, ByVal eventName As String)
    Dim e As IEntity = Session.Source().Get(New DbObjectKey(objKey))
    e.GenerateEvent(session, eventName)
End Sub

Public Function CCC_GetPersonDepartmentViaEmail (EmailAddress As String) As String
    Dim f = session.SqlFormatter()
    Dim p2 = session.Source().Get(Of Person)(Query.From("Person").Where(f.Comparison("DefaultEmailAddress", EmailAddress, ValType.String)).SelectNone())
    Return p2.GetDepartment(session).FullPath
End Function

9.3+

Building the projects also creates .nupkg and .nupkg.zip files.

For just local usage, copy the nupkg files to your frontend's NuGet subdirectory. The zip file could be used with software loader to distribute it. I just added this for reference.

Please note, I have not tested how this behaves when replacing the NuGet package. After using it, there is a copy in the NuGet cache (%USERPROFILE%\.nuget\packages). The cache might be stale if you just replace the NuGet package in the NuGet subfolder, I couldn't tell up to this point in time.

Working example, pretty much the same as above:

#If Not SCRIPTDEBUGGER
#R OneIMExtensions
#R TypedWrapperExtensions
Imports OneIMExtensions
Imports TypedWrapperExtensions
#End If

Public Sub CCC_FireEvent (objKey As String, ByVal eventName As String)
    Dim e As IEntity = Session.Source().Get(New DbObjectKey(objKey))
    e.GenerateEvent(session, eventName)
End Sub

Public Function CCC_GetPersonDepartmentViaEmail (EmailAddress As String) As String
    Dim f = session.SqlFormatter()
    Dim p2 = session.Source().Get(Of Person)(Query.From("Person").Where(f.Comparison("DefaultEmailAddress", EmailAddress, ValType.String)).SelectNone())
    Return p2.GetDepartment(session).FullPath
End Function

Can you add SP5 of release 25.4?

I should do this fairly soon after a release.

I don't want to wait, can I add SP5 of release 25.4?

You could. You would have to edit localsettings.props and add a new configuration for the new version.

Can I compile this in VS Code?

Yes, this should work. However, the project doesn't ship a .vscode dir at this point so has no default commands.

Can I compile this on Linux?

Yes, if you have dotnet installed, but you need to acquire the dynamic TypedWrappers DLL for your DB (referenced via the AppDataLocation). There is no build script for this, but it's possible to run e.g. dotnet build -c OneIM930. I have used these with Linqpad started via Wine, but I've not tried if they have any use on the Linux host itself. In theory, 9.3+ DLLs should just work (except for GuiExtensions.dll which specifically target windows), e.g. with Powershell, csharprepl, etc. but getting everything into place with dependencies could be somewhat tricky, the LinqPad section below might give an idea. The .NET Framework DLLs for <9.3 lack a framework, this might or might not work via Mono.

localsettings.props examples:

<Project>
  <PropertyGroup>
    <AppDataLocation>/home/User/Wineprefixes/OneIM.Net/drive_c/users/User/Local Settings/Application Data/One Identity/One Identity Manager/AssemblyCache</AppDataLocation>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)'=='OneIM930'">
    <OneIMBaseDir>/home/User/Workdir/OneIM/binaries/930</OneIMBaseDir>
    <!-- replace AssemblySuffix with suffix observed in table DialogScriptAssembly -->
    <AssemblySuffix>4o1ozmqeN2QRKPailzL3lAyw8ZkfwSD</AssemblySuffix>
    <!-- replace ; in ConnectionString with %3b -->
    <ConnectionString>Data Source=OneIMDB-93,1493%3bInitial Catalog=OneIM%3bUser ID=OneIM_Admin%3bPassword=Pass_word1</ConnectionString>
    <VIDBVersion>9.3.0-278876</VIDBVersion>
    <VIBaseVersion>9.3.0-278876</VIBaseVersion>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)'=='OneIM922'">
    <OneIMBaseDir>/home/User/Workdir/OneIM/binaries/922</OneIMBaseDir>
    <!-- replace AssemblySuffix with suffix observed in table DialogScriptAssembly -->
    <AssemblySuffix>jLNCmXb9scleKXvAKZDZu9qGv79W7oVU</AssemblySuffix>
    <!-- replace ; in ConnectionString with %3b -->
    <ConnectionString>Data Source=OneIMDB-92,1492%3bInitial Catalog=OneIM%3bUser ID=OneIM_Admin%3bPassword=Pass_word1</ConnectionString>
  </PropertyGroup>
</Project>

One challenge with .NET is to get the NuGet packages into the package cache. While on Windows, this just works with running DbCompiler. But DbCompiler and DbCompilerCMD are net80-windows executables, so can't be run on Linux. The easiest way was to create a local Nuget source, e.g. /home/USER/OneIM/NuGet, copy all .nupkg files from OneIM installation NuGet subfolder to this directory, and add it as a local NuGet source, e.g. dotnet nuget add source /home/USER/OneIM/NuGet -n OneIM-local. At that point, restoring the projects works, e.g. dotnet restore /p:Configuration=OneIM930. I might add something to the build config to automate this in the future.

How do I use this in LinqPad?

before 9.3

Add references for

  • GuiExtensions.dll
  • OneIMExtensions.dll
  • TypedWrapperExtension.dll
  • TypedWrappers_<assembly suffix>.dll
  • probably VI.DB.dll and VI.Base.dll depending on what you want to do

Customizer or Authenticator dependencies should be dynamically resolved, so long as you use the provided assembly resolver. Here is a code example:

Utils.Initialize();
var logger = Utils.GetLogger();
var session = Utils.GetDefaultOneIMSession();

var c = session.Source().Get<DialogDatabase>(Query.From("DialogDatabase").SelectNone());
c.EditionVersion.Dump();

var pobj = new DbObjectKey("<Key><T>Person</T><P>3d679e00-b66f-483b-92a4-0dc64c5c9d4e</P></Key>");
var p = session.Source().Get(pobj);
p.GetValue("Firstname").String.Dump();

var pt = session.Source().Get<Person>(pobj);
String.Format("{0}, {1}", pt.LastName, pt.FirstName).Dump();

The first line ensures that customizer and authenticator dependencies are found.

See Linqpad 5 screenshots in the assets subfolder, might link them here eventually. ;)

9.3+

  • Add references for
    • GuiExtensions.dll
    • GuiExtensions.deps.json
    • OneIMExtensions.dll
    • OneIMExtensions.deps.json
    • TypedWrapperExtensions.dll
    • TypedWrapperExtensions.deps.json
    • TypedWrappers_<assembly suffix>.dll
  • In the advanced tab, select "Copy all assemblies..." and "with native and platform-specific..."

Linqpad 8 uses NuGet packages. This includes OneIM dependencies. In order to get OneIM NuGet packages into the NuGet package cache, run a full compile in DBCompiler.

Theoretically, Linqpad 8 should also get along with the NuGet packages for the above DLLs. I have not tried this.

See Linqpad 8 screenshots in the assets subfolder.

Can I use a connection dialog?

Yes, see ConnectDialogExtensions.GetOneIMSessionFromDialog(), with limitations:

  • I could not get this to work from LinqPad 8. At least not using .NET 8. LinqPad has its own AssemblyLoadContext for user queries. This way, both a 8.0 (from .NET, loaded by LinqPad) and 9.0 (dependency of VI.CommonDialogs.dll) System.Drawing.Common are loaded. As a result, I see an error Method not found: 'Void System.Windows.Forms.Control.set_Font(System.Drawing.Font)'. It's possible there is a clever way of loading assemblies in a clever way with LinqPads separate contexts in mind. It seems also possible to just use .NET 9.0 for the LinqPad script.

Can you extend this with foo or bar?

Theoretically, yes. But I do not intend for this VS project to be a utility library or cover implementation specific use cases. Like stated above, it's for demonstration and reference purposes. Frankly, OneIM is a job and a hobby, and being the pragmatic idealist that I am, with this personal project I do not wish to compete with my or anyone elses commercial activities. Any likely additions I could think of couldn't be provided under the given licence anyway.

The project's primary value from my point of view is the MSBuild stuff, which I figured out over time in my spare time. The OneIM API related parts on the other hand are in no way spectacular, clever or unique. And very likely never will be.

That said, if you do have any suggestions, feel free to open an issue.

Can I extend this with foo or bar?

I've added a permissive licence so feel free to do whatever you like. Again, the OneIM specific stuff is entirely basic, but I did spend a bit of my spare time to come up with the build configurations.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages