├── .gitattributes ├── .github ├── FUNDING.yml └── stale.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md └── src ├── Lithnet.ResourceManagement.Automation.Installer ├── Components.wxs ├── Lithnet.ResourceManagement.Automation.Binaries.wxs ├── Lithnet.ResourceManagement.Automation.Installer.wixproj └── Product.wxs ├── Lithnet.ResourceManagement.Automation.sln ├── Lithnet.ResourceManagement.Automation ├── AttributeValueArrayList.cs ├── ConfigSyncControl.cs ├── Enums │ ├── ApprovalDecision.cs │ ├── AttributeOperationType.cs │ ├── AttributeValueType.cs │ ├── ResourceOperationType.cs │ └── SchemaRefreshEvent.cs ├── Examples │ ├── ChangeLogResource.xml │ ├── ConfigImportExample.xml │ ├── Email Notifications │ │ ├── EmailTemplateAccountExpiry.html │ │ └── WFAccountExpiry.xoml │ └── Variables.xml ├── FodyWeavers.xml ├── GetApprovalRequest.cs ├── GetResource.cs ├── GetResourceCount.cs ├── ImportRMConfig.cs ├── Lithnet.ResourceManagement.Automation.csproj ├── LithnetRMA.Help.pshproj ├── LithnetRMA.psd1 ├── NewResource.cs ├── NewResourceUpdateTemplate.cs ├── NewXpathExpression.cs ├── NewXpathQuery.cs ├── NewXpathQueryGroup.cs ├── Properties │ └── AssemblyInfo.cs ├── RemoveResource.cs ├── RmaObject.cs ├── RmaSearchPager.cs ├── RmcWrapper.cs ├── SaveResource.cs ├── SearchResources.cs ├── SearchResourcesPaged.cs ├── SetPendingApprovalRequest.cs ├── SetResourceManagementClient.cs ├── UpdateResourceManagementClientSchema.cs ├── XmlConfig │ ├── AttributeOperation.cs │ ├── ConfigFile.cs │ ├── ResourceOperation.cs │ ├── Variable.cs │ └── Variables.cs ├── app.config ├── en-us │ └── Lithnet.ResourceManagement.Automation.dll-help.xml ├── packages.config └── packages │ └── repositories.config └── Lithnet.ResourceManagement.Resolver ├── Lithnet.ResourceManagement.Resolver.csproj ├── MrmResolver.cs └── Properties └── AssemblyInfo.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | custom: ['https://lithnet.io/donate'] 3 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: stale 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed in 7 days if no further activity occurs. 15 | # Comment to post when closing a stale issue. Set to `false` to disable 16 | closeComment: false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Roslyn cache directories 20 | *.ide/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | _NCrunch_* 98 | .*crunch*.local.xml 99 | 100 | # MightyMoose 101 | *.mm.* 102 | AutoTest.Net/ 103 | 104 | # Web workbench (sass) 105 | .sass-cache/ 106 | 107 | # Installshield output folder 108 | [Ee]xpress/ 109 | 110 | # DocProject is a documentation generator add-in 111 | DocProject/buildhelp/ 112 | DocProject/Help/*.HxT 113 | DocProject/Help/*.HxC 114 | DocProject/Help/*.hhc 115 | DocProject/Help/*.hhk 116 | DocProject/Help/*.hhp 117 | DocProject/Help/Html2 118 | DocProject/Help/html 119 | 120 | # Click-Once directory 121 | publish/ 122 | 123 | # Publish Web Output 124 | *.[Pp]ublish.xml 125 | *.azurePubxml 126 | ## TODO: Comment the next line if you want to checkin your 127 | ## web deploy settings but do note that will include unencrypted 128 | ## passwords 129 | #*.pubxml 130 | 131 | # NuGet Packages Directory 132 | packages/* 133 | ## TODO: If the tool you use requires repositories.config 134 | ## uncomment the next line 135 | #!packages/repositories.config 136 | 137 | # Enable "build/" folder in the NuGet Packages folder since 138 | # NuGet packages use it for MSBuild targets. 139 | # This line needs to be after the ignore of the build folder 140 | # (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | # LightSwitch generated files 187 | GeneratedArtifacts/ 188 | _Pvt_Extensions/ 189 | ModelManifest.xml 190 | /src/packages 191 | 192 | .vs/ -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | https://lithnet.io/contact-us. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution guidelines 2 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 3 | 4 | - Reporting a bug 5 | - Discussing the current state of the code 6 | - Submitting a fix 7 | - Proposing new features 8 | 9 | ## We Develop with Github 10 | We use github to host code, to track issues and feature requests, as well as accept pull requests. 11 | 12 | ## All Code Changes Happen Through Pull Requests 13 | Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests: 14 | 15 | 1. Fork the repo and create your branch from `master`. 16 | 2. If you've added code that should be tested, add tests. 17 | 3. If you've changed APIs, update the documentation. 18 | 4. Ensure the test suite passes. 19 | 5. Issue the pull request. 20 | 21 | ## Any contributions you make will be under the MIT Software License 22 | In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. 23 | 24 | ## Report bugs using Github's [issues](https://github.com/lithnet/resourcemanagement-powershell/issues) 25 | We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy! 26 | 27 | ## Write bug reports with detail, background, and sample code 28 | The more information we have, the easier it is for us to troubleshoot your issue 29 | 30 | **Great Bug Reports** tend to have: 31 | 32 | - A quick summary and/or background 33 | - Steps to reproduce 34 | - Be specific! 35 | - Give sample code if you can 36 | - What you expected would happen 37 | - What actually happens 38 | - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) 39 | 40 | ## License 41 | By contributing, you agree that your contributions will be licensed under its MIT License. 42 | 43 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Lithnet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/lithnet/resourcemanagement-powershell/wiki/images/logo-ex-small.png) 2 | # FIM/MIM Service PowerShell Module 3 | The Lithnet FIM/MIM Service PowerShell module is designed to make working with the FIM Service faster and easier. It abstracts away the complexity of the FIM Service and the FIMAutomation PowerShell module, and exposes a robust set of cmdlets for creating, updating, deleting and searching for resources. 4 | 5 | ### Guides 6 | * [Installing the module](https://github.com/lithnet/resourcemanagement-powershell/wiki/installing-the-module) 7 | * [Quick reference guide](https://github.com/lithnet/resourcemanagement-powershell/wiki/quick-reference-guide) 8 | * [Working with different data and attribute types](https://github.com/lithnet/resourcemanagement-powershell/wiki/working-with-different-data-and-attribute-types) 9 | * Using the PowerShell module for [configuration management](https://github.com/lithnet/resourcemanagement-powershell/wiki/configuration-management) 10 | * [Cmdlet Reference](https://github.com/lithnet/resourcemanagement-powershell/wiki/cmdlet-reference) 11 | 12 | ### Download the module 13 | Download the [current release](https://github.com/lithnet/resourcemanagement-powershell/releases/) 14 | 15 | ## How can I contribute to the project? 16 | * Found an issue and want us to fix it? [Log it](https://github.com/lithnet/resourcemanagement-powershell/issues) 17 | * Want to fix an issue yourself or add functionality? Clone the project and submit a pull request 18 | 19 | ## Enterprise support 20 | Lithnet offer enterprise support plans for our open-source products. Deploy our tools with confidence that you have the backing of the dedicated Lithnet support team if you run into any issues, have questions, or need advice. Simply fill out the [request form](https://lithnet.io/products/mim), let us know the number of users you are managing with your MIM implementation, and we'll put together a quote. 21 | 22 | ### Keep up to date 23 | * [Visit our blog](http://blog.lithnet.io) 24 | * [Follow us on twitter](https://twitter.com/lithnet_io)![](http://twitter.com/favicon.ico) 25 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation.Installer/Components.wxs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation.Installer/Lithnet.ResourceManagement.Automation.Binaries.wxs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation.Installer/Lithnet.ResourceManagement.Automation.Installer.wixproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 6 | x64 7 | 3.10 8 | b9eb58e9-c770-4a1a-a4f5-fac5ede1714f 9 | 2.0 10 | Lithnet.ResourceManagement.Automation 11 | Package 12 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets 13 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets 14 | 15 | 16 | Debug 17 | bin\$(Configuration)\ 18 | obj\$(Platform)\$(Configuration)\ 19 | 20 | 21 | bin\$(Configuration)\ 22 | obj\$(Platform)\$(Configuration)\ 23 | True 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Lithnet.ResourceManagement.Automation 32 | {4c4beb83-82ff-4625-b8c7-d547c654228a} 33 | True 34 | True 35 | Binaries;Content;Satellites 36 | INSTALLFOLDER 37 | 38 | 39 | 40 | 41 | $(WixExtDir)\WixNetFxExtension.dll 42 | WixNetFxExtension 43 | 44 | 45 | $(WixExtDir)\WixUIExtension.dll 46 | WixUIExtension 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | "C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /sha1 "$(CSCERTTHUMBPRINT)" /t http://timestamp.digicert.com /fd sha256 /v "$(TargetFileName)" 55 | 56 | 64 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation.Installer/Product.wxs: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 1 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithnet.ResourceManagement.Automation", "Lithnet.ResourceManagement.Automation\Lithnet.ResourceManagement.Automation.csproj", "{4C4BEB83-82FF-4625-B8C7-D547C654228A}" 7 | EndProject 8 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Lithnet.ResourceManagement.Automation.Installer", "Lithnet.ResourceManagement.Automation.Installer\Lithnet.ResourceManagement.Automation.Installer.wixproj", "{B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|Mixed Platforms = Debug|Mixed Platforms 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|Mixed Platforms = Release|Mixed Platforms 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 23 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 24 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Debug|x86.ActiveCfg = Debug|Any CPU 25 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 28 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Release|Mixed Platforms.Build.0 = Release|Any CPU 29 | {4C4BEB83-82FF-4625-B8C7-D547C654228A}.Release|x86.ActiveCfg = Release|Any CPU 30 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Debug|Any CPU.ActiveCfg = Debug|x64 31 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 32 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Debug|Mixed Platforms.Build.0 = Debug|x64 33 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Debug|x86.ActiveCfg = Debug|x64 34 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Release|Any CPU.ActiveCfg = Release|x64 35 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Release|Mixed Platforms.ActiveCfg = Release|x64 36 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Release|Mixed Platforms.Build.0 = Release|x64 37 | {B9EB58E9-C770-4A1A-A4F5-FAC5EDE1714F}.Release|x86.ActiveCfg = Release|x64 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/AttributeValueArrayList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Management.Automation; 7 | using Lithnet.ResourceManagement.Client; 8 | using Microsoft.ResourceManagement.WebServices; 9 | 10 | namespace Lithnet.ResourceManagement.Automation 11 | { 12 | public class AttributeValueArrayList : ArrayList 13 | { 14 | public AttributeValueArrayList() 15 | : base() 16 | { 17 | } 18 | 19 | public AttributeValueArrayList(ICollection c) 20 | : base(c) 21 | { 22 | } 23 | 24 | public override void AddRange(ICollection c) 25 | { 26 | foreach (object item in c) 27 | { 28 | if (item is RmaObject rmaObject) 29 | { 30 | base.Add(rmaObject.InternalObject.ObjectID); 31 | } 32 | else 33 | { 34 | base.Add(item); 35 | } 36 | } 37 | } 38 | 39 | public override int Add(object value) 40 | { 41 | if (value is RmaObject rmaObject) 42 | { 43 | return base.Add(rmaObject.InternalObject.ObjectID); 44 | } 45 | else 46 | { 47 | return base.Add(value); 48 | } 49 | } 50 | 51 | public override void Remove(object obj) 52 | { 53 | if (base.Contains(obj)) 54 | { 55 | // obj is already a unique identifier 56 | base.Remove(obj); 57 | return; 58 | } 59 | 60 | switch (obj) 61 | { 62 | case RmaObject rmaObject: 63 | // obj is an existing object 64 | base.Remove(rmaObject.InternalObject.ObjectID); 65 | return; 66 | 67 | case Guid guid1: 68 | // obj is a guid 69 | base.Remove(new UniqueIdentifier(guid1)); 70 | return; 71 | 72 | case string s when Guid.TryParse(s, out Guid guid): 73 | // obj is a string in GUID format 74 | base.Remove(new UniqueIdentifier(guid)); 75 | return; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/ConfigSyncControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Lithnet.ResourceManagement.Automation 7 | { 8 | internal static class ConfigSyncControl 9 | { 10 | public static string CurrentPath { get; set; } 11 | 12 | public static ConfigFile CurrentConfig { get; set; } 13 | 14 | public static bool Preview { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Enums/ApprovalDecision.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | public enum ApprovalDecision 10 | { 11 | Approve = 0, 12 | 13 | Reject = 1, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Enums/AttributeOperationType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | [Flags] 10 | public enum AttributeOperationType 11 | { 12 | [XmlEnum("none")] 13 | None = 0, 14 | 15 | [XmlEnum("add")] 16 | Add = 1, 17 | 18 | [XmlEnum("replace")] 19 | Replace = 2, 20 | 21 | [XmlEnum("delete")] 22 | Delete = 4 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Enums/AttributeValueType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | public enum AttributeValueType 10 | { 11 | [XmlEnum("value")] 12 | Value = 0, 13 | 14 | [XmlEnum("file")] 15 | File = 1, 16 | 17 | [XmlEnum("ref")] 18 | Reference = 2, 19 | 20 | [XmlEnum("xmlref")] 21 | XmlReference = 3, 22 | 23 | [XmlEnum("filter")] 24 | XPathFilter = 4 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Enums/ResourceOperationType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Lithnet.ResourceManagement.Automation 7 | { 8 | [Flags] 9 | public enum ResourceOperationType 10 | { 11 | None = 0, 12 | Add = 1, 13 | Update = 2, 14 | Delete = 4 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Enums/SchemaRefreshEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | [Flags] 10 | public enum SchemaRefreshEvent 11 | { 12 | [XmlEnum("none")] 13 | None = 0, 14 | 15 | [XmlEnum("before-operation")] 16 | BeforeOperation = 1, 17 | 18 | [XmlEnum("after-operation")] 19 | AfterOperation = 2 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Examples/ChangeLogResource.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | Name 9 | 10 | 11 | changeLogEntry 12 | This resource defines a component and its version within the FIM service 13 | Change Log Entry 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Name 22 | 23 | 24 | version 25 | Version 26 | The current version of the component 27 | Text 28 | false 29 | 30 | 31 | 32 | 33 | 34 | Name 35 | 36 | 37 | details 38 | Details 39 | Contains the change log history for this component 40 | Text 41 | false 42 | 43 | 44 | 45 | 46 | 47 | BoundAttributeType 48 | BoundObjectType 49 | 50 | 51 | changeLogResource 52 | detailsAttribute 53 | false 54 | Details 55 | Contains the change log history for this component 56 | 57 | 58 | 59 | 60 | 61 | BoundAttributeType 62 | BoundObjectType 63 | 64 | 65 | changeLogResource 66 | versionAttribute 67 | false 68 | Version 69 | The current version of the component 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | DisplayName 78 | 79 | 80 | All change log entries 81 | Contains all change log entries 82 | /changeLogEntry 83 | 84 | 85 | 86 | 87 | 88 | DisplayName 89 | 90 | 91 | _Administrators can control change log entries 92 | Allows administrators to read, create, modify and delete change log entries 93 | false 94 | Request 95 | 96 | Modify 97 | Add 98 | Remove 99 | Create 100 | Delete 101 | Read 102 | true 103 | * 104 | Set|DisplayName|Administrators 105 | changeLogEntrySet 106 | changeLogEntrySet 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Examples/ConfigImportExample.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | DisplayName 14 | 15 | 16 | _Users pending expiration 17 | Contains all accounts with elapsed RS1021 Notification dates, but have not yet expired 18 | /Person[(rs1021NotificationDate < fn:current-dateTime()) and (rs1021Date > fn:current-dateTime()) and Email != '!Invalid!'] 19 | 20 | 21 | 22 | 23 | 24 | DisplayName 25 | 26 | 27 | _Account expiration notification to user 28 | An email template used to send a notification to user that their account is about to expire 29 | Notification 30 | .\Email Notifications\EmailTemplateAccountExpiry.html 31 | Your IT account will expire soon 32 | 33 | 34 | 35 | 36 | 37 | DisplayName 38 | 39 | 40 | _Account expiration notification email to user workflow 41 | Sends an account expiry notification email to users email address 42 | .\Email Notifications\WFAccountExpiry.xoml 43 | Action 44 | false 45 | 46 | 47 | 48 | 49 | 50 | DisplayName 51 | 52 | 53 | _Notification - Send account expiration notification email to accounts within the expiration window 54 | Triggers the "##xmlref:accountExpirationWorkflowDefinition:DisplayName##" workflow when a user account transitions into the "##xmlref:accountExpirationSet:DisplayName##" set 55 | * 56 | TransitionIn 57 | accountExpirationWorkflowDefinition 58 | false 59 | false 60 | SetTransition 61 | accountExpirationSet 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | DisplayName 71 | 72 | 73 | FIM Service: Email Notifications 74 | 1.5 75 | RN 05/04/2015 76 | Added DEV5 URL 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Examples/Email Notifications/EmailTemplateAccountExpiry.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | Account expiry notification email 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 37 | 38 | 39 |
13 | 14 | 15 | 16 | 17 | 18 | 32 | 33 | 34 | 35 |
   19 |
20 |

Dear [//Target/DisplayName],

21 | 22 |

Please be advised that your IT account [//Target/AccountName] will expire on:

23 |

24 | [//WorkflowData/aestExpDate] Australian Eastern Standard Time
25 | [//WorkflowData/myExpDate] Malaysian Time
26 | [//WorkflowData/zaExpDate] South African Time

27 |

28 |

You will no longer be able to access any IT resources after this date.

29 | 30 |

If you have any queries regarding your IT account, please contact your local Service Desk

31 |
 
36 |
40 | 41 | 71 | 72 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Examples/Email Notifications/WFAccountExpiry.xoml: -------------------------------------------------------------------------------- 1 |  9 | 10 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Examples/Variables.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/GetApprovalRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.Get, "ApprovalRequest")] 14 | public class GetApprovalRequest : PSCmdlet 15 | { 16 | [Parameter(Mandatory = false, Position = 1)] 17 | public ApprovalStatus Status { get; set; } 18 | 19 | protected override void ProcessRecord() 20 | { 21 | ISearchResultCollection results = RmcWrapper.Client.GetApprovals(this.Status); 22 | 23 | foreach (ResourceObject result in results) 24 | { 25 | this.WriteObject(new RmaObject(result)); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/GetResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | using System.Globalization; 11 | 12 | namespace Lithnet.ResourceManagement.Automation 13 | { 14 | [Cmdlet(VerbsCommon.Get, "Resource", DefaultParameterSetName = "GetResourceByKey")] 15 | public class GetResource : PSCmdlet //, IDynamicParameters 16 | { 17 | [Parameter(ParameterSetName = "GetResource", ValueFromPipeline = true, Mandatory = true, Position = 1)] 18 | public object ID { get; set; } 19 | 20 | [Parameter(ParameterSetName = "GetResourceByKey", Mandatory = true, ValueFromPipeline = true, Position = 1)] 21 | [Parameter(ParameterSetName = "GetResourceByKeys", Mandatory = true, ValueFromPipeline = true, Position = 1)] 22 | public string ObjectType { get; set; } 23 | //{ 24 | // get 25 | // { 26 | // return (string)this.MyInvocation.BoundParameters["ObjectType"]; 27 | // } 28 | //} 29 | 30 | [Parameter(ParameterSetName = "GetResourceByKey", Mandatory = true, Position = 2)] 31 | public string AttributeName { get; set; } 32 | //public string AttributeName 33 | //{ 34 | // get 35 | // { 36 | // return (string)this.MyInvocation.BoundParameters["AttributeName"]; 37 | // } 38 | //} 39 | 40 | [Parameter(ParameterSetName = "GetResourceByKey", Mandatory = true, Position = 3)] 41 | public object AttributeValue { get; set; } 42 | 43 | [Parameter(ParameterSetName = "GetResourceByKeys", Mandatory = true, Position = 2)] 44 | public Hashtable AttributeValuePairs { get; set; } 45 | 46 | [Parameter(ParameterSetName = "GetResourceByKey", Mandatory = false, Position = 4)] 47 | [Parameter(ParameterSetName = "GetResourceByKeys", Mandatory = false, Position = 3)] 48 | [Parameter(ParameterSetName = "GetResource", Mandatory = false, Position = 2)] 49 | public string[] AttributesToGet { get; set; } 50 | 51 | [Parameter(ParameterSetName = "GetResourceByKey", Mandatory = false, Position = 5)] 52 | [Parameter(ParameterSetName = "GetResourceByKeys", Mandatory = false, Position = 4)] 53 | [Parameter(ParameterSetName = "GetResource", Mandatory = false, Position = 3)] 54 | public string Locale { get; set; } 55 | 56 | protected override void ProcessRecord() 57 | { 58 | ResourceObject resource; 59 | CultureInfo locale = null; 60 | 61 | if (this.Locale != null) 62 | { 63 | locale = new CultureInfo(this.Locale); 64 | } 65 | 66 | if (this.ID != null) 67 | { 68 | object item = null; 69 | 70 | if (this.ID is PSObject pso) 71 | { 72 | item = pso.BaseObject; 73 | } 74 | else 75 | { 76 | item = this.ID; 77 | } 78 | 79 | if (item is UniqueIdentifier uniqueID) 80 | { 81 | resource = RmcWrapper.Client.GetResource(uniqueID, this.AttributesToGet, locale); 82 | 83 | if (resource == null) 84 | { 85 | throw new ResourceNotFoundException(); 86 | } 87 | 88 | this.WriteObject(new RmaObject(resource)); 89 | return; 90 | } 91 | 92 | if (item is string stringID) 93 | { 94 | resource = RmcWrapper.Client.GetResource(stringID, this.AttributesToGet, locale); 95 | 96 | if (resource == null) 97 | { 98 | throw new ResourceNotFoundException(); 99 | } 100 | 101 | this.WriteObject(new RmaObject(resource)); 102 | return; 103 | } 104 | 105 | if (item is Guid guidID) 106 | { 107 | resource = RmcWrapper.Client.GetResource(guidID, this.AttributesToGet, locale); 108 | 109 | if (resource == null) 110 | { 111 | throw new ResourceNotFoundException(); 112 | } 113 | 114 | this.WriteObject(new RmaObject(resource)); 115 | return; 116 | } 117 | 118 | throw new ArgumentException($"The object type of the ID parameter was unknown. {this.ID.GetType().FullName}"); 119 | } 120 | 121 | if (this.AttributeValuePairs != null) 122 | { 123 | resource = RmcWrapper.Client.GetResourceByKey(this.ObjectType, this.HashTableToDictionary(this.AttributeValuePairs), this.AttributesToGet, locale); 124 | 125 | if (resource == null) 126 | { 127 | throw new ResourceNotFoundException(); 128 | } 129 | 130 | this.WriteObject(new RmaObject(resource)); 131 | return; 132 | } 133 | else 134 | { 135 | resource = RmcWrapper.Client.GetResourceByKey(this.ObjectType, this.AttributeName, this.AttributeValue, this.AttributesToGet, locale); 136 | 137 | if (resource == null) 138 | { 139 | throw new ResourceNotFoundException(); 140 | } 141 | 142 | this.WriteObject(new RmaObject(resource)); 143 | return; 144 | } 145 | } 146 | 147 | private Dictionary HashTableToDictionary(Hashtable table) 148 | { 149 | Dictionary dictionary = new Dictionary(); 150 | 151 | foreach (DictionaryEntry entry in table) 152 | { 153 | dictionary.Add(entry.Key.ToString(), entry.Value); 154 | } 155 | 156 | return dictionary; 157 | } 158 | 159 | //public object GetDynamicParameters() 160 | //{ 161 | // RuntimeDefinedParameterDictionary runtimeDefinedParameterDictionary = new RuntimeDefinedParameterDictionary(); 162 | // RuntimeDefinedParameter parameter; 163 | 164 | // parameter = RmcWrapper.GetObjectTypeParameter("ObjectType", true, 1, false, "GetResourceByKey"); 165 | // parameter.Attributes.Add(new ParameterAttribute() { ParameterSetName = "GetResourceByKeys", Position = 1, Mandatory = true }); 166 | // runtimeDefinedParameterDictionary.Add(parameter.Name, parameter); 167 | 168 | // string objectType = null; 169 | // if (this.MyInvocation.BoundParameters.ContainsKey("ObjectType")) 170 | // { 171 | // objectType = this.ObjectType; 172 | // } 173 | 174 | // parameter = RmcWrapper.GetAttributeNameParameter("AttributeName", true, 2, objectType, "GetResourceByKey"); 175 | // runtimeDefinedParameterDictionary.Add(parameter.Name, parameter); 176 | 177 | // return runtimeDefinedParameterDictionary; 178 | //} 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/GetResourceCount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.Get, "ResourceCount")] 14 | public class GetResourceCount : Cmdlet 15 | { 16 | [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 1)] 17 | public object XPath { get; set; } 18 | 19 | protected override void ProcessRecord() 20 | { 21 | IEnumerable attributes = null; 22 | string filter = this.GetQueryString(); 23 | attributes = new List() { "ObjectID" }; 24 | 25 | ISearchResultCollection results = RmcWrapper.Client.GetResources(filter, 0, attributes); 26 | this.WriteObject(results.Count); 27 | } 28 | 29 | private string GetQueryString() 30 | { 31 | XPathExpression expression = this.XPath as XPathExpression; 32 | 33 | if (expression != null) 34 | { 35 | return expression.ToString(false); 36 | } 37 | 38 | PSObject wrappedObject = this.XPath as PSObject; 39 | 40 | if (wrappedObject != null) 41 | { 42 | expression = wrappedObject.BaseObject as XPathExpression; 43 | 44 | if (expression != null) 45 | { 46 | return expression.ToString(false); 47 | } 48 | 49 | throw new ArgumentException("The XPath parameter must be a string or XPathExpression object"); 50 | } 51 | 52 | if (!(this.XPath is string)) 53 | { 54 | throw new ArgumentException("The XPath parameter must be a string or XPathExpression object"); 55 | } 56 | 57 | return (string)this.XPath; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/ImportRMConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management.Automation; 6 | using System.Xml; 7 | using System.Xml.Serialization; 8 | using System.IO; 9 | 10 | namespace Lithnet.ResourceManagement.Automation 11 | { 12 | [Cmdlet(VerbsData.Import, "RMConfig")] 13 | public class ImportRMConfig : PSCmdlet 14 | { 15 | [Parameter(ValueFromPipeline = false, Mandatory = true, Position = 1)] 16 | public string File { get; set; } 17 | 18 | [Parameter(ValueFromPipeline = false, Mandatory = false, Position = 2)] 19 | public SwitchParameter Preview { get; set; } 20 | 21 | private ConfigFile config; 22 | 23 | protected override void BeginProcessing() 24 | { 25 | this.WriteVerbose("Loading rules file"); 26 | XmlSerializer s = new XmlSerializer(typeof(ConfigFile)); 27 | 28 | string filename; 29 | string basePath = this.SessionState.Path.CurrentFileSystemLocation.Path; 30 | if (Path.IsPathRooted(this.File)) 31 | { 32 | filename = this.File; 33 | } 34 | else 35 | { 36 | filename = Path.Combine(basePath, this.File); 37 | } 38 | 39 | using (StreamReader sr = System.IO.File.OpenText(filename)) 40 | { 41 | XmlReader xr = XmlReader.Create(sr); 42 | this.config = (ConfigFile)s.Deserialize(xr); 43 | } 44 | 45 | this.config.Variables.LoadFileVariables(basePath); 46 | ResourceOperation.LogEvent += ResourceOperation_LogEvent; 47 | 48 | ConfigSyncControl.CurrentConfig = this.config; 49 | ConfigSyncControl.CurrentPath = basePath; 50 | ConfigSyncControl.Preview = this.Preview; 51 | } 52 | 53 | protected override void ProcessRecord() 54 | { 55 | int count = 0; 56 | 57 | foreach (ResourceOperation op in this.config.Operations) 58 | { 59 | ProgressRecord p = new ProgressRecord(0, string.Format("Processing import operations{0}...", this.Preview ? " (preview)" : string.Empty) 60 | , string.Format("Processing {0}", op.ID)); 61 | p.PercentComplete = (count / this.config.Operations.Count) * 100; 62 | this.WriteProgress(p); 63 | op.ExecuteOperation(); 64 | this.WriteVerbose(this.builder.ToString()); 65 | this.builder = new StringBuilder(); 66 | } 67 | } 68 | 69 | protected override void EndProcessing() 70 | { 71 | ConfigSyncControl.CurrentConfig = null; 72 | } 73 | 74 | private void ResourceOperation_LogEvent(object sender, string e) 75 | { 76 | this.builder.AppendLine(e); 77 | } 78 | 79 | private StringBuilder builder = new StringBuilder(); 80 | } 81 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Lithnet.ResourceManagement.Automation.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4C4BEB83-82FF-4625-B8C7-D547C654228A} 8 | Library 9 | Properties 10 | Lithnet.ResourceManagement.Automation 11 | Lithnet.ResourceManagement.Automation 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | false 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | 39 | ..\packages\Lithnet.ResourceManagement.Client.1.0.6623.18312\lib\net40\Lithnet.ResourceManagement.Client.dll 40 | 41 | 42 | ..\packages\Lithnet.ResourceManagement.Client.1.0.6623.18312\lib\net40\Microsoft.ResourceManagement.dll 43 | True 44 | 45 | 46 | 47 | 48 | 49 | False 50 | C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll 51 | False 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Designer 99 | 100 | 101 | Designer 102 | 103 | 104 | 105 | 106 | PreserveNewest 107 | 108 | 109 | 110 | PreserveNewest 111 | 112 | 113 | Designer 114 | 115 | 116 | Designer 117 | 118 | 119 | Designer 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 140 | 141 | 142 | 143 | 144 | 145 | $(PostBuildEventDependsOn); 146 | PostBuildMacros; 147 | 148 | "C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /sha1 "$(CSCERTTHUMBPRINT)" /t http://timestamp.digicert.com /fd sha256 /v "$(TargetFileName)" 149 | 150 | "C:\Program Files\Debugging Tools for Windows (x64)\symstore" add /f "$(TargetDir)*.pdb" /s \\localhost\symbols /t "$(ProjectName)" /v "@(VersionNumber)" 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 183 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/LithnetRMA.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'LithnetRMAutomation' 3 | # 4 | # Generated by: Ryan Newington 5 | # 6 | # Generated on: 04/08/2015 7 | # 8 | 9 | @{ 10 | 11 | # Version number of this module. 12 | ModuleVersion = '$version$' 13 | 14 | # ID used to uniquely identify this module 15 | GUID = 'd7c36446-aca6-418a-a2a3-cbfc32016a52' 16 | 17 | # Author of this module 18 | Author = 'Ryan Newington' 19 | 20 | # Company or vendor of this module 21 | CompanyName = 'Lithnet' 22 | 23 | # Copyright statement for this module 24 | Copyright = '' 25 | 26 | # Description of the functionality provided by this module 27 | Description = 'Lithnet Resource Management Client for PowerShell' 28 | 29 | # Minimum version of the Windows PowerShell engine required by this module 30 | PowerShellVersion = '3.0' 31 | 32 | # Name of the Windows PowerShell host required by this module 33 | PowerShellHostName = '' 34 | 35 | # Minimum version of the Windows PowerShell host required by this module 36 | PowerShellHostVersion = '' 37 | 38 | # Minimum version of the .NET Framework required by this module 39 | DotNetFrameworkVersion = '4.0' 40 | 41 | # Minimum version of the common language runtime (CLR) required by this module 42 | CLRVersion = '' 43 | 44 | # Processor architecture (None, X86, Amd64, IA64) required by this module 45 | ProcessorArchitecture = 'Amd64' 46 | 47 | # Modules that must be imported into the global environment prior to importing this module 48 | RequiredModules = @() 49 | 50 | # Assemblies that must be loaded prior to importing this module 51 | #RequiredAssemblies = '' 52 | 53 | # Script files (.ps1) that are run in the caller's environment prior to importing this module 54 | ScriptsToProcess = @() 55 | 56 | # Type files (.ps1xml) to be loaded when importing this module 57 | TypesToProcess = @() 58 | 59 | # Format files (.ps1xml) to be loaded when importing this module 60 | FormatsToProcess = @() 61 | 62 | # Modules to import as nested modules of the module specified in ModuleToProcess 63 | NestedModules = 'Lithnet.ResourceManagement.Automation.dll' 64 | 65 | # Functions to export from this module 66 | FunctionsToExport = '*' 67 | 68 | # Cmdlets to export from this module 69 | CmdletsToExport = '*' 70 | 71 | # Variables to export from this module 72 | VariablesToExport = '*' 73 | 74 | # Aliases to export from this module 75 | AliasesToExport = '*' 76 | 77 | # List of all modules packaged with this module 78 | ModuleList = @() 79 | 80 | # List of all files packaged with this module 81 | FileList = @() 82 | 83 | # Private data to pass to the module specified in ModuleToProcess 84 | PrivateData = '' 85 | 86 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/NewResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.New, "Resource")] 14 | public class NewResource : Cmdlet 15 | { 16 | [Parameter(Mandatory = true, Position = 1)] 17 | public string ObjectType { get; set; } 18 | 19 | protected override void ProcessRecord() 20 | { 21 | this.WriteObject(new RmaObject(RmcWrapper.Client.CreateResource(this.ObjectType))); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/NewResourceUpdateTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.New, "ResourceUpdateTemplate")] 14 | public class NewResourceUpdateTemplate : Cmdlet 15 | { 16 | [Parameter(Mandatory = true, Position = 1)] 17 | public string ObjectType { get; set; } 18 | 19 | [Parameter(Mandatory = true, Position = 2)] 20 | public object ID { get; set; } 21 | 22 | protected override void ProcessRecord() 23 | { 24 | UniqueIdentifier uniqueID = this.ID as UniqueIdentifier; 25 | 26 | if (uniqueID != null) 27 | { 28 | this.WriteObject(new RmaObject(RmcWrapper.Client.CreateResourceTemplateForUpdate(this.ObjectType, uniqueID))); 29 | return; 30 | } 31 | 32 | string stringID = this.ID as string; 33 | 34 | if (stringID != null) 35 | { 36 | uniqueID = new UniqueIdentifier(stringID); 37 | this.WriteObject(new RmaObject(RmcWrapper.Client.CreateResourceTemplateForUpdate(this.ObjectType, uniqueID))); 38 | return; 39 | } 40 | 41 | Guid? guidID = this.ID as Guid?; 42 | 43 | if (guidID != null) 44 | { 45 | uniqueID = new UniqueIdentifier(guidID.Value); 46 | this.WriteObject(new RmaObject(RmcWrapper.Client.CreateResourceTemplateForUpdate(this.ObjectType, uniqueID))); 47 | return; 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/NewXpathExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Management; 7 | using System.Management.Automation; 8 | using Microsoft.ResourceManagement.WebServices; 9 | using System.Collections; 10 | using Lithnet.ResourceManagement.Client; 11 | 12 | namespace Lithnet.ResourceManagement.Automation 13 | { 14 | [Cmdlet(VerbsCommon.New, "XPathExpression")] 15 | public class NewXPathExpression : PSCmdlet //, IDynamicParameters 16 | { 17 | [Parameter(Mandatory = true, Position = 1)] 18 | public string ObjectType {get;set;} 19 | //{ 20 | // get 21 | // { 22 | // return (string)this.MyInvocation.BoundParameters["ObjectType"]; 23 | // } 24 | //} 25 | 26 | [Parameter(Mandatory = false, Position = 2, ValueFromPipeline = true)] 27 | public IXPathQueryObject QueryObject { get; set; } 28 | 29 | [Parameter(Mandatory = false, Position = 3)] 30 | public string DereferenceAttribute { get; set; } 31 | 32 | [Parameter(Mandatory = false, Position = 4)] 33 | public SwitchParameter WrapFilterXml { get; set; } 34 | 35 | protected override void ProcessRecord() 36 | { 37 | if (this.DereferenceAttribute == null) 38 | { 39 | this.WriteObject(new XPathExpression(this.ObjectType, this.QueryObject, this.WrapFilterXml.IsPresent)); 40 | } 41 | else 42 | { 43 | this.WriteObject(new XPathDereferencedExpression(this.ObjectType, this.DereferenceAttribute, this.QueryObject, this.WrapFilterXml.IsPresent)); 44 | } 45 | } 46 | 47 | //public object GetDynamicParameters() 48 | //{ 49 | // var runtimeDefinedParameterDictionary = new RuntimeDefinedParameterDictionary(); 50 | // RuntimeDefinedParameter parameter = RmcWrapper.GetObjectTypeParameter("ObjectType", true, 1, true, null); 51 | 52 | // runtimeDefinedParameterDictionary.Add(parameter.Name, parameter); 53 | 54 | // return runtimeDefinedParameterDictionary; 55 | //} 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/NewXpathQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.New, "XPathQuery")] 14 | public class NewXPathQuery : PSCmdlet//, IDynamicParameters 15 | { 16 | [Parameter(Mandatory = true, Position = 1)] 17 | public string AttributeName {get;set;} 18 | //{ 19 | // get 20 | // { 21 | // return (string)this.MyInvocation.BoundParameters["AttributeName"]; 22 | // } 23 | //} 24 | 25 | [Parameter(Mandatory = true, Position = 2)] 26 | public ComparisonOperator Operator { get; set; } 27 | 28 | [Parameter(Mandatory = false, Position = 3)] 29 | public object Value { get; set; } 30 | 31 | [Parameter(Mandatory = false, Position = 4)] 32 | public SwitchParameter Negate { get; set; } 33 | 34 | protected override void ProcessRecord() 35 | { 36 | object unwrappedValue; 37 | 38 | PSObject wrappedObject = this.Value as PSObject; 39 | 40 | if (wrappedObject != null) 41 | { 42 | unwrappedValue = wrappedObject.BaseObject; 43 | } 44 | else 45 | { 46 | unwrappedValue = this.Value; 47 | } 48 | 49 | this.WriteObject( new XPathQuery(this.AttributeName, this.Operator, unwrappedValue, this.Negate.IsPresent)); 50 | } 51 | 52 | 53 | //public object GetDynamicParameters() 54 | //{ 55 | // var runtimeDefinedParameterDictionary = new RuntimeDefinedParameterDictionary(); 56 | // RuntimeDefinedParameter parameter = RmcWrapper.GetAttributeNameParameter("AttributeName", true, 1, null, null); 57 | 58 | // runtimeDefinedParameterDictionary.Add(parameter.Name, parameter); 59 | 60 | // return runtimeDefinedParameterDictionary; 61 | //} 62 | } 63 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/NewXpathQueryGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.New, "XPathQueryGroup")] 14 | public class NewXPathQueryGroup : Cmdlet 15 | { 16 | [Parameter(Mandatory = true, Position = 1)] 17 | public GroupOperator Operator { get; set; } 18 | 19 | [Parameter(Mandatory = false, Position = 2, ValueFromPipeline = true)] 20 | public IXPathQueryObject[] Queries { get; set; } 21 | 22 | protected override void ProcessRecord() 23 | { 24 | this.WriteObject(new XPathQueryGroup(this.Operator, this.Queries)); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Lithnet PowerShell module for FIM")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Lithnet.ResourceManagement.Automation")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d195d846-ac23-498c-a45e-88f490d24ab1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.*")] 36 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/RemoveResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.Remove, "Resource", DefaultParameterSetName="ObjectIDString")] 14 | public class RemoveResource : Cmdlet 15 | { 16 | [Parameter(Mandatory = true, Position = 1, ParameterSetName = "ID")] 17 | public object[] ID { get; set; } 18 | 19 | [Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true, ParameterSetName = "ResourceObject")] 20 | public RmaObject[] ResourceObjects { get; set; } 21 | 22 | protected override void ProcessRecord() 23 | { 24 | if (this.ID != null) 25 | { 26 | List ids = new List(); 27 | 28 | foreach (object id in this.ID) 29 | { 30 | string idString = id as string; 31 | Guid? idGuid = id as Guid?; 32 | UniqueIdentifier idUniqueID = id as UniqueIdentifier; 33 | 34 | if (idString != null) 35 | { 36 | ids.Add(new UniqueIdentifier(idString)); 37 | } 38 | else if (idGuid.HasValue) 39 | { 40 | ids.Add(new UniqueIdentifier(idGuid.Value)); 41 | } 42 | else if (idUniqueID != null) 43 | { 44 | ids.Add(idUniqueID); 45 | } 46 | } 47 | 48 | RmcWrapper.Client.DeleteResources(ids); 49 | } 50 | else if (this.ResourceObjects != null) 51 | { 52 | RmcWrapper.Client.DeleteResources(this.ResourceObjects.Select(t => t.InternalObject)); 53 | } 54 | else 55 | { 56 | throw new InvalidOperationException(); 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/RmaObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Management.Automation; 7 | using Lithnet.ResourceManagement.Client; 8 | 9 | namespace Lithnet.ResourceManagement.Automation 10 | { 11 | public class RmaObject : PSObject 12 | { 13 | internal RmaObject(ResourceObject resource) 14 | { 15 | this.InternalObject = resource; 16 | this.LoadProperties(); 17 | } 18 | 19 | internal ResourceObject InternalObject { get; set; } 20 | 21 | internal void ReloadProperties() 22 | { 23 | foreach (var property in this.Properties) 24 | { 25 | this.Properties.Remove(property.Name); 26 | } 27 | 28 | this.LoadProperties(); 29 | } 30 | 31 | private void LoadProperties() 32 | { 33 | foreach (AttributeValue value in this.InternalObject.Attributes.OrderBy(t => t.AttributeName)) 34 | { 35 | PSNoteProperty prop; 36 | if (value.Attribute.IsMultivalued) 37 | { 38 | prop = new PSNoteProperty(value.AttributeName, new AttributeValueArrayList((ICollection)value.Value)); 39 | } 40 | else 41 | { 42 | prop = new PSNoteProperty(value.AttributeName, value.Value); 43 | } 44 | 45 | this.Properties.Add(prop); 46 | } 47 | } 48 | 49 | internal ResourceObject GetResourceWithAppliedChanges() 50 | { 51 | foreach (var property in this.Properties) 52 | { 53 | if (this.InternalObject.Attributes[property.Name].Attribute.IsReadOnly) 54 | { 55 | continue; 56 | } 57 | 58 | IEnumerable resourceValues = property.Value as IEnumerable; 59 | 60 | if (resourceValues != null) 61 | { 62 | this.SetMultivaluedAttribute(property, resourceValues); 63 | } 64 | else 65 | { 66 | this.SetSingleValuedAttribute(property, property.Value); 67 | } 68 | } 69 | 70 | return this.InternalObject; 71 | } 72 | 73 | private void SetMultivaluedAttribute(PSPropertyInfo property, IEnumerable resourceValues) 74 | { 75 | List newValues = new List(); 76 | 77 | foreach (object value in resourceValues) 78 | { 79 | RmaObject resourceValue = value as RmaObject; 80 | 81 | if (resourceValue != null) 82 | { 83 | newValues.Add(resourceValue.InternalObject.ObjectID); 84 | } 85 | else 86 | { 87 | newValues.Add(this.UnwrapPSObject(value)); 88 | } 89 | } 90 | 91 | this.InternalObject.Attributes[property.Name].SetValue(newValues); 92 | } 93 | 94 | private void SetSingleValuedAttribute(PSPropertyInfo property, object value) 95 | { 96 | RmaObject resourceValue = property.Value as RmaObject; 97 | 98 | if (resourceValue != null) 99 | { 100 | this.InternalObject.Attributes[property.Name].SetValue(resourceValue.InternalObject.ObjectID); 101 | } 102 | else 103 | { 104 | this.InternalObject.Attributes[property.Name].SetValue(this.UnwrapPSObject(property.Value)); 105 | } 106 | } 107 | 108 | private object UnwrapPSObject(object value) 109 | { 110 | PSObject psObject = value as PSObject; 111 | 112 | if (psObject != null) 113 | { 114 | return psObject.BaseObject; 115 | } 116 | else 117 | { 118 | return value; 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/RmaSearchPager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Lithnet.ResourceManagement.Client; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | public class RmaSearchPager 10 | { 11 | SearchResultPager pager; 12 | 13 | internal RmaSearchPager(SearchResultPager pager) 14 | { 15 | this.pager = pager; 16 | } 17 | 18 | public int TotalCount 19 | { 20 | get 21 | { 22 | return this.pager.TotalCount; 23 | } 24 | } 25 | 26 | public int CurrentIndex 27 | { 28 | get 29 | { 30 | return this.pager.CurrentIndex; 31 | } 32 | set 33 | { 34 | this.pager.CurrentIndex = value; 35 | } 36 | } 37 | 38 | public int PageSize 39 | { 40 | get 41 | { 42 | return this.pager.PageSize; 43 | } 44 | set 45 | { 46 | this.pager.PageSize = value; 47 | } 48 | } 49 | 50 | public bool HasMoreItems 51 | { 52 | get 53 | { 54 | return this.pager.HasMoreItems; 55 | } 56 | } 57 | 58 | public RmaObject[] GetNextPage() 59 | { 60 | List results = new List(); 61 | 62 | foreach(ResourceObject resource in this.pager.GetNextPage()) 63 | { 64 | results.Add(new RmaObject(resource)); 65 | } 66 | 67 | return results.ToArray(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/RmcWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Lithnet.ResourceManagement.Client; 6 | using System.Reflection; 7 | using Microsoft.Win32; 8 | using System.IO; 9 | using System.Management.Automation; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | internal static class RmcWrapper 14 | { 15 | private static ResourceManagementClient client; 16 | 17 | public static ResourceManagementClient Client 18 | { 19 | get 20 | { 21 | if (RmcWrapper.client == null) 22 | { 23 | RmcWrapper.client = new ResourceManagementClient(); 24 | } 25 | 26 | return RmcWrapper.client; 27 | } 28 | 29 | internal set 30 | { 31 | RmcWrapper.client = value; 32 | } 33 | } 34 | 35 | public static RuntimeDefinedParameter GetObjectTypeParameter(string paramName, bool mandatory, int position, bool allowWildcard, string parameterSetName) 36 | { 37 | RuntimeDefinedParameter parameter = new RuntimeDefinedParameter(); 38 | parameter.Name = paramName; 39 | parameter.ParameterType = typeof(string); 40 | IList objectTypes = ResourceManagementSchema.GetObjectTypes().ToList(); 41 | 42 | if (objectTypes.Count > 0) 43 | { 44 | List objectTypeNames = objectTypes.OrderBy(t => t.SystemName).Select(t => t.SystemName).ToList(); 45 | if (allowWildcard) 46 | { 47 | objectTypeNames.Add("*"); 48 | } 49 | 50 | ValidateSetAttribute setAttribute = new ValidateSetAttribute(objectTypeNames.ToArray()); 51 | parameter.Attributes.Add(setAttribute); 52 | } 53 | 54 | ParameterAttribute paramAttribute = new ParameterAttribute(); 55 | paramAttribute.Mandatory = mandatory; 56 | paramAttribute.Position = position; 57 | paramAttribute.ParameterSetName = parameterSetName; 58 | parameter.Attributes.Add(paramAttribute); 59 | return parameter; 60 | } 61 | 62 | public static RuntimeDefinedParameter GetAttributeNameParameter(string paramName, bool mandatory, int position, string objectType, string parameterSetName) 63 | { 64 | RuntimeDefinedParameter parameter = new RuntimeDefinedParameter(); 65 | parameter.Name = paramName; 66 | parameter.ParameterType = typeof(string); 67 | 68 | if (objectType == null) 69 | { 70 | List attributeNames = new List(); 71 | 72 | IList objectTypes = ResourceManagementSchema.GetObjectTypes().ToList(); 73 | 74 | if (objectTypes.Count > 0) 75 | { 76 | foreach (ObjectTypeDefinition type in objectTypes) 77 | { 78 | attributeNames.AddRange(type.Attributes.Select(t => t.SystemName)); 79 | } 80 | 81 | if (attributeNames.Count > 0) 82 | { 83 | ValidateSetAttribute setAttribute = new ValidateSetAttribute(attributeNames.Distinct().OrderBy(t => t).ToArray()); 84 | parameter.Attributes.Add(setAttribute); 85 | } 86 | } 87 | } 88 | else 89 | { 90 | 91 | if (ResourceManagementSchema.ContainsObjectType(objectType)) 92 | { 93 | ValidateSetAttribute setAttribute = new ValidateSetAttribute(ResourceManagementSchema.GetObjectType(objectType).Attributes.OrderBy(t => t.SystemName).Select(t => t.SystemName).ToArray()); 94 | parameter.Attributes.Add(setAttribute); 95 | } 96 | } 97 | 98 | ParameterAttribute paramAttribute = new ParameterAttribute(); 99 | paramAttribute.Mandatory = mandatory; 100 | paramAttribute.Position = position; 101 | paramAttribute.ParameterSetName = parameterSetName; 102 | parameter.Attributes.Add(paramAttribute); 103 | return parameter; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/SaveResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | using System.Globalization; 11 | 12 | namespace Lithnet.ResourceManagement.Automation 13 | { 14 | [Cmdlet(VerbsData.Save, "Resource")] 15 | public class SaveResource : Cmdlet 16 | { 17 | [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 1)] 18 | public RmaObject[] Resources { get; set; } 19 | 20 | [Parameter(Mandatory = false)] 21 | public SwitchParameter Parallel { get; set; } 22 | 23 | [Parameter(Mandatory = false)] 24 | public string Locale { get; set; } 25 | 26 | protected override void ProcessRecord() 27 | { 28 | try 29 | { 30 | IEnumerable creatingObjects = this.Resources.Where(t => t.InternalObject.ModificationType == OperationType.Create).ToList(); 31 | 32 | if (this.Locale != null || this.Resources.Any(t => t.InternalObject.Locale != null)) 33 | { 34 | CultureInfo locale = null; 35 | 36 | if (this.Locale != null) 37 | { 38 | locale = new CultureInfo(this.Locale); 39 | } 40 | 41 | if (this.Resources.Length > 1) 42 | { 43 | this.WriteWarning("Composite save disabled as locale parameter has been specified or at least one resource has been localized"); 44 | } 45 | 46 | foreach (ResourceObject r in this.Resources.Select(t => t.GetResourceWithAppliedChanges())) 47 | { 48 | RmcWrapper.Client.SaveResource(r, locale); 49 | } 50 | } 51 | else 52 | { 53 | if (this.Parallel.IsPresent) 54 | { 55 | RmcWrapper.Client.SaveResourcesParallel(this.Resources.Select(t => t.GetResourceWithAppliedChanges()), -1); 56 | } 57 | else 58 | { 59 | RmcWrapper.Client.SaveResources(this.Resources.Select(t => t.GetResourceWithAppliedChanges())); 60 | } 61 | } 62 | 63 | foreach (RmaObject resource in creatingObjects) 64 | { 65 | resource.ReloadProperties(); 66 | } 67 | } 68 | catch (AuthorizationRequiredException ex) 69 | { 70 | this.WriteVerbose("Authorization required: " + ex.ResourceReference); 71 | this.WriteObject(ex.ResourceReference); 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/SearchResources.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using Microsoft.ResourceManagement.WebServices.WSEnumeration; 9 | using System.Collections; 10 | using Lithnet.ResourceManagement.Client; 11 | using System.Globalization; 12 | 13 | namespace Lithnet.ResourceManagement.Automation 14 | { 15 | [Cmdlet(VerbsCommon.Search, "Resources", DefaultParameterSetName = "ConstrainedQueryByTypeRaw")] 16 | public class SearchResources : Cmdlet 17 | { 18 | [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 1)] 19 | public object XPath { get; set; } 20 | 21 | [Parameter(ParameterSetName = "ConstrainedQueryByAttributesRaw", Mandatory = false, Position = 2)] 22 | public string[] AttributesToGet { get; set; } 23 | 24 | [Parameter(ParameterSetName = "ConstrainedQueryByTypeRaw", Mandatory = false, Position = 2)] 25 | public string ExpectedObjectType { get; set; } 26 | 27 | [Parameter(ParameterSetName = "UnconstrainedQueryRaw", Mandatory = false, Position = 2)] 28 | public SwitchParameter Unconstrained { get; set; } 29 | 30 | [Parameter] 31 | public int MaxResults { get; set; } 32 | 33 | [Parameter] 34 | public int PageSize { get; set; } 35 | 36 | [Parameter] 37 | public string[] SortAttributes { get; set; } 38 | 39 | [Parameter] 40 | public SwitchParameter Descending { get; set; } 41 | 42 | [Parameter] 43 | public string Locale { get; set; } 44 | 45 | protected override void ProcessRecord() 46 | { 47 | CultureInfo locale = null; 48 | 49 | if (this.Locale != null) 50 | { 51 | locale = new CultureInfo(this.Locale); 52 | } 53 | 54 | IEnumerable attributes = null; 55 | string filter = this.GetQueryString(); 56 | 57 | if (!this.Unconstrained.IsPresent) 58 | { 59 | if (this.AttributesToGet == null || this.AttributesToGet.Length == 0) 60 | { 61 | if (string.IsNullOrWhiteSpace(this.ExpectedObjectType)) 62 | { 63 | attributes = new List() { "ObjectID" }; 64 | } 65 | else 66 | { 67 | ObjectTypeDefinition objectType = ResourceManagementSchema.GetObjectType(this.ExpectedObjectType); 68 | attributes = objectType.Attributes.Select(t => t.SystemName); 69 | } 70 | } 71 | else 72 | { 73 | attributes = this.AttributesToGet; 74 | } 75 | } 76 | 77 | int count = 0; 78 | int pageSize; 79 | 80 | if (this.PageSize > 0) 81 | { 82 | pageSize = this.PageSize; 83 | } 84 | else 85 | { 86 | pageSize = 200; 87 | } 88 | 89 | if (this.MaxResults > 0 && this.MaxResults < pageSize) 90 | { 91 | pageSize = this.MaxResults; 92 | } 93 | 94 | List sortCriteria = new List(); 95 | if (this.SortAttributes != null) 96 | { 97 | foreach (string attribute in this.SortAttributes) 98 | { 99 | sortCriteria.Add(new SortingAttribute(attribute, !this.Descending)); 100 | } 101 | } 102 | 103 | foreach (ResourceObject resource in RmcWrapper.Client.GetResources(filter, pageSize, attributes, sortCriteria, locale)) 104 | { 105 | this.WriteObject(new RmaObject(resource)); 106 | count++; 107 | 108 | if (this.MaxResults > 0 && count >= this.MaxResults) 109 | { 110 | break; 111 | } 112 | } 113 | } 114 | 115 | private string GetQueryString() 116 | { 117 | XPathExpression expression = this.XPath as XPathExpression; 118 | 119 | if (expression != null) 120 | { 121 | return expression.ToString(false); 122 | } 123 | 124 | PSObject wrappedObject = this.XPath as PSObject; 125 | 126 | if (wrappedObject != null) 127 | { 128 | expression = wrappedObject.BaseObject as XPathExpression; 129 | 130 | if (expression != null) 131 | { 132 | return expression.ToString(false); 133 | } 134 | 135 | throw new ArgumentException("The XPath parameter must be a string or XPathExpression object"); 136 | } 137 | 138 | if (!(this.XPath is string)) 139 | { 140 | throw new ArgumentException("The XPath parameter must be a string or XPathExpression object"); 141 | } 142 | 143 | return (string)this.XPath; 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/SearchResourcesPaged.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using Microsoft.ResourceManagement.WebServices.WSEnumeration; 9 | using System.Collections; 10 | using Lithnet.ResourceManagement.Client; 11 | using System.Globalization; 12 | 13 | namespace Lithnet.ResourceManagement.Automation 14 | { 15 | [Cmdlet(VerbsCommon.Search, "ResourcesPaged", DefaultParameterSetName = "ConstrainedQueryByTypeRaw")] 16 | public class SearchResourcesPaged : Cmdlet 17 | { 18 | [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 1)] 19 | public object XPath { get; set; } 20 | 21 | [Parameter(ParameterSetName = "ConstrainedQueryByAttributesRaw", Mandatory = false, Position = 2)] 22 | public string[] AttributesToGet { get; set; } 23 | 24 | [Parameter(ParameterSetName = "ConstrainedQueryByTypeRaw", Mandatory = false, Position = 2)] 25 | public string ExpectedObjectType { get; set; } 26 | 27 | [Parameter(ParameterSetName = "UnconstrainedQueryRaw", Mandatory = false, Position = 2)] 28 | public SwitchParameter Unconstrained { get; set; } 29 | 30 | [Parameter] 31 | public int PageSize { get; set; } 32 | 33 | [Parameter] 34 | public string[] SortAttributes { get; set; } 35 | 36 | [Parameter] 37 | public SwitchParameter Descending { get; set; } 38 | 39 | [Parameter] 40 | public string Locale { get; set; } 41 | 42 | protected override void ProcessRecord() 43 | { 44 | CultureInfo locale = null; 45 | 46 | if (this.Locale != null) 47 | { 48 | locale = new CultureInfo(this.Locale); 49 | } 50 | 51 | IEnumerable attributes = null; 52 | string filter = this.GetQueryString(); 53 | 54 | if (!this.Unconstrained.IsPresent) 55 | { 56 | if (this.AttributesToGet == null || this.AttributesToGet.Length == 0) 57 | { 58 | if (string.IsNullOrWhiteSpace(this.ExpectedObjectType)) 59 | { 60 | attributes = new List() { "ObjectID" }; 61 | } 62 | else 63 | { 64 | ObjectTypeDefinition objectType = ResourceManagementSchema.GetObjectType(this.ExpectedObjectType); 65 | attributes = objectType.Attributes.Select(t => t.SystemName); 66 | } 67 | } 68 | else 69 | { 70 | attributes = this.AttributesToGet; 71 | } 72 | } 73 | 74 | int pageSize; 75 | 76 | if (this.PageSize > 0) 77 | { 78 | pageSize = this.PageSize; 79 | } 80 | else 81 | { 82 | pageSize = 200; 83 | } 84 | 85 | List sortCriteria = new List(); 86 | if (this.SortAttributes != null) 87 | { 88 | foreach (string attribute in this.SortAttributes) 89 | { 90 | sortCriteria.Add(new SortingAttribute(attribute, !this.Descending)); 91 | } 92 | } 93 | 94 | this.WriteObject(new RmaSearchPager(RmcWrapper.Client.GetResourcesPaged(filter, pageSize, attributes, sortCriteria, locale))); 95 | } 96 | 97 | private string GetQueryString() 98 | { 99 | XPathExpression expression = this.XPath as XPathExpression; 100 | 101 | if (expression != null) 102 | { 103 | return expression.ToString(false); 104 | } 105 | 106 | PSObject wrappedObject = this.XPath as PSObject; 107 | 108 | if (wrappedObject != null) 109 | { 110 | expression = wrappedObject.BaseObject as XPathExpression; 111 | 112 | if (expression != null) 113 | { 114 | return expression.ToString(false); 115 | } 116 | 117 | throw new ArgumentException("The XPath parameter must be a string or XPathExpression object"); 118 | } 119 | 120 | if (!(this.XPath is string)) 121 | { 122 | throw new ArgumentException("The XPath parameter must be a string or XPathExpression object"); 123 | } 124 | 125 | return (string)this.XPath; 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/SetPendingApprovalRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Management; 6 | using System.Management.Automation; 7 | using Microsoft.ResourceManagement.WebServices; 8 | using System.Collections; 9 | using Lithnet.ResourceManagement.Client; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | [Cmdlet(VerbsCommon.Set, "PendingApprovalRequest")] 14 | public class SetPendingApprovalRequest : PSCmdlet 15 | { 16 | [Parameter(ValueFromPipeline = true, Mandatory = true, Position = 1)] 17 | public RmaObject ApprovalObject { get; set; } 18 | 19 | [Parameter(ValueFromPipeline = false, Mandatory = false, Position = 2)] 20 | public ApprovalDecision Decision { get; set; } 21 | 22 | [Parameter(ValueFromPipeline = false, Mandatory = false, Position = 3)] 23 | public string Reason { get; set; } 24 | 25 | protected override void ProcessRecord() 26 | { 27 | ResourceObject r = this.ApprovalObject.InternalObject; 28 | RmcWrapper.Client.Approve(r, this.Decision == ApprovalDecision.Approve, this.Reason); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/SetResourceManagementClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Management.Automation; 3 | using System.Net; 4 | using System.Runtime.InteropServices; 5 | using System.Security; 6 | using Lithnet.ResourceManagement.Client; 7 | 8 | namespace Lithnet.ResourceManagement.Automation 9 | { 10 | [Cmdlet(VerbsCommon.Set, "ResourceManagementClient")] 11 | public class SetResourceManagementClient : Cmdlet 12 | { 13 | [Parameter(Mandatory = true, Position = 0)] 14 | public string BaseAddress { get; set; } 15 | 16 | [Parameter(ValueFromPipeline = true, Position = 1)] 17 | public PSCredential Credentials { get; set; } 18 | 19 | [Parameter(Position = 2)] 20 | public string ServicePrincipalName { get; set; } 21 | 22 | [Parameter(Position = 3)] 23 | public bool ForceKerberos { get; set; } 24 | 25 | [Parameter(Position = 4)] 26 | public SwitchParameter RefreshSchema { get; set; } 27 | 28 | protected override void EndProcessing() 29 | { 30 | NetworkCredential creds = null; 31 | 32 | if (this.Credentials != null) 33 | { 34 | creds = this.Credentials.GetNetworkCredential(); 35 | } 36 | 37 | Uri baseUri; 38 | 39 | try 40 | { 41 | if (!Uri.TryCreate(this.BaseAddress, UriKind.Absolute, out baseUri)) 42 | { 43 | baseUri = new Uri($"http://{this.BaseAddress}:5725"); 44 | } 45 | } 46 | catch (Exception ex) 47 | { 48 | this.WriteError(new ErrorRecord(ex, "InvalidUri", ErrorCategory.InvalidArgument, this.BaseAddress)); 49 | return; 50 | } 51 | 52 | RmcWrapper.Client = new Client.ResourceManagementClient(baseUri, creds, this.ServicePrincipalName, !this.ForceKerberos); 53 | 54 | if (this.RefreshSchema.IsPresent || !baseUri.Host.Equals(ResourceManagementSchema.SchemaEndpoint?.Host, StringComparison.OrdinalIgnoreCase)) 55 | { 56 | RmcWrapper.Client.RefreshSchema(); 57 | } 58 | 59 | base.EndProcessing(); 60 | } 61 | 62 | private string ConvertToUnsecureString(SecureString securePassword) 63 | { 64 | if (securePassword == null) 65 | throw new ArgumentNullException(nameof(securePassword)); 66 | 67 | IntPtr unmanagedString = IntPtr.Zero; 68 | try 69 | { 70 | unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword); 71 | return Marshal.PtrToStringUni(unmanagedString); 72 | } 73 | finally 74 | { 75 | Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/UpdateResourceManagementClientSchema.cs: -------------------------------------------------------------------------------- 1 |  2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Management; 7 | using System.Management.Automation; 8 | using Microsoft.ResourceManagement.WebServices; 9 | using System.Collections; 10 | using Lithnet.ResourceManagement.Client; 11 | 12 | namespace Lithnet.ResourceManagement.Automation 13 | { 14 | [Cmdlet(VerbsData.Update, "ResourceManagementClientSchema")] 15 | public class UpdateResourceManagementClientSchema : Cmdlet 16 | { 17 | protected override void ProcessRecord() 18 | { 19 | RmcWrapper.Client.RefreshSchema(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/XmlConfig/AttributeOperation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | using System.IO; 7 | using Lithnet.ResourceManagement.Client; 8 | using System.Globalization; 9 | using System.Text.RegularExpressions; 10 | using Microsoft.ResourceManagement.WebServices; 11 | using System.Security; 12 | 13 | namespace Lithnet.ResourceManagement.Automation 14 | { 15 | public class AttributeOperation 16 | { 17 | private const string filterTextFormat = "{0}"; 18 | 19 | [XmlAttribute(AttributeName = "operation")] 20 | public AttributeOperationType Operation { get; set; } 21 | 22 | [XmlAttribute(AttributeName = "name")] 23 | public string Name { get; set; } 24 | 25 | [XmlAttribute(AttributeName = "type")] 26 | public AttributeValueType ValueType { get; set; } 27 | 28 | [XmlText()] 29 | public string Value { get; set; } 30 | 31 | [XmlIgnore] 32 | public object ExpandedValue 33 | { 34 | get 35 | { 36 | return this.GetValue(); 37 | } 38 | } 39 | 40 | internal void ExecuteOperation(ResourceObject resource, ResourceOperationType resourceOpType) 41 | { 42 | if (resource == null) 43 | { 44 | throw new ArgumentNullException("resource"); 45 | } 46 | 47 | this.ValidateResourceOperationType(resourceOpType); 48 | 49 | switch (this.Operation) 50 | { 51 | case AttributeOperationType.None: 52 | return; 53 | 54 | case AttributeOperationType.Add: 55 | this.PerformAttributeAdd(resource); 56 | break; 57 | 58 | case AttributeOperationType.Replace: 59 | this.PerformAttributeReplace(resource); 60 | break; 61 | 62 | case AttributeOperationType.Delete: 63 | this.PerformAttributeDelete(resource); 64 | break; 65 | 66 | default: 67 | throw new ArgumentException("Unknown or unsupported operation type"); 68 | } 69 | } 70 | 71 | private void PerformAttributeAdd(ResourceObject resource) 72 | { 73 | if (!resource.Attributes[this.Name].Attribute.IsMultivalued) 74 | { 75 | this.PerformAttributeReplace(resource); 76 | } 77 | else 78 | { 79 | object newValue = this.ExpandedValue; 80 | 81 | resource.Attributes[this.Name].AddValue(newValue); 82 | } 83 | } 84 | 85 | private void PerformAttributeReplace(ResourceObject resource) 86 | { 87 | object newValue = this.ExpandedValue; 88 | 89 | if (newValue is string) 90 | { 91 | if (string.IsNullOrEmpty((string)newValue)) 92 | { 93 | if (resource.Attributes[this.Name].IsNull) 94 | { 95 | return; 96 | } 97 | } 98 | } 99 | 100 | resource.Attributes[this.Name].SetValue(newValue); 101 | } 102 | 103 | private void PerformAttributeDelete(ResourceObject resource) 104 | { 105 | object newValue = this.ExpandedValue; 106 | 107 | resource.Attributes[this.Name].RemoveValue(newValue); 108 | } 109 | 110 | private void ValidateResourceOperationType(ResourceOperationType resourceOpType) 111 | { 112 | switch (this.Operation) 113 | { 114 | case AttributeOperationType.None: 115 | break; 116 | 117 | case AttributeOperationType.Replace: 118 | case AttributeOperationType.Delete: 119 | case AttributeOperationType.Add: 120 | if (resourceOpType == ResourceOperationType.Delete) 121 | { 122 | throw new ArgumentException("Cannot perform an attribute change on a delete operation"); 123 | } 124 | 125 | break; 126 | 127 | default: 128 | throw new ArgumentException("Unknown or unsupported AttributeOperationType: " + this.Operation.ToString()); 129 | } 130 | } 131 | 132 | private object GetValue() 133 | { 134 | if (this.Value == null) 135 | { 136 | return null; 137 | } 138 | 139 | switch (this.ValueType) 140 | { 141 | case AttributeValueType.Value: 142 | return this.ExpandVariables(this.Value); 143 | 144 | case AttributeValueType.File: 145 | return this.GetFileContent(this.ExpandVariables(this.Value)); 146 | 147 | case AttributeValueType.Reference: 148 | return this.GetReference(this.Value); 149 | 150 | case AttributeValueType.XmlReference: 151 | return this.GetXmlReference(this.Value); 152 | 153 | case AttributeValueType.XPathFilter: 154 | return this.BuildFilterAttribute(this.Value); 155 | 156 | default: 157 | throw new ArgumentException("Unknown value type " + this.Value.ToString()); 158 | } 159 | } 160 | 161 | private string ExpandVariables(string input) 162 | { 163 | string expandedInput = input; 164 | 165 | if ( ConfigSyncControl.CurrentConfig.Variables != null && ConfigSyncControl.CurrentConfig.Variables.Items != null) 166 | { 167 | foreach (Variable variable in ConfigSyncControl.CurrentConfig.Variables.Items) 168 | { 169 | expandedInput = expandedInput.Replace(variable.Name, variable.ExpandedValue); 170 | } 171 | } 172 | 173 | foreach (Match match in Regex.Matches(expandedInput, @"\#\#xmlref:(.+?):(.*?)\#\#")) 174 | { 175 | if (match.Groups.Count >= 2) 176 | { 177 | string xmlRefName = match.Groups[1].Value; 178 | ResourceObject xmlRef = this.GetXmlReferenceResource(xmlRefName); 179 | if (xmlRef == null) 180 | { 181 | throw new ArgumentException("The input string contained the xmlref pattern '{0}', but the object could not be resolved"); 182 | } 183 | 184 | string xmlDeRefAttributeName = "ObjectID"; 185 | if (match.Groups.Count > 2) 186 | { 187 | string groupValue = match.Groups[2].Value; 188 | 189 | if (!string.IsNullOrWhiteSpace(groupValue)) 190 | { 191 | xmlDeRefAttributeName = match.Groups[2].Value; 192 | } 193 | } 194 | 195 | object xmlDeRefValue = xmlRef.Attributes[xmlDeRefAttributeName].Value; 196 | 197 | UniqueIdentifier xmlDerefID = xmlDeRefValue as UniqueIdentifier; 198 | if (xmlDerefID != null) 199 | { 200 | xmlDeRefValue = xmlDerefID.Value; 201 | } 202 | 203 | expandedInput = expandedInput.Replace(match.Value, xmlDeRefValue == null ? null : xmlDeRefValue.ToString()); 204 | } 205 | } 206 | 207 | return expandedInput; 208 | } 209 | 210 | private string GetFileContent(string filename) 211 | { 212 | if (!Path.IsPathRooted(filename)) 213 | { 214 | filename = Path.Combine(ConfigSyncControl.CurrentPath, filename); 215 | } 216 | 217 | return this.ExpandVariables(File.ReadAllText(filename)); 218 | } 219 | 220 | private string BuildFilterAttribute(string xpath) 221 | { 222 | string unescapedText = this.ExpandVariables(xpath); 223 | string escapedText = unescapedText.Replace("<", "<").Replace(">", ">"); 224 | string returnValue = string.Format(filterTextFormat, escapedText); 225 | return returnValue; 226 | } 227 | 228 | private string GetReference(string value) 229 | { 230 | string[] split = this.ExpandVariables(value).Split('|'); 231 | if (split.Length != 3) 232 | { 233 | throw new ArgumentException(string.Format("The attribute operation of {0} on attribute {1} specifies a reference type, but does not have a string in the value of ObjectType|AttributeName|AttributeValue. The invalid value was {2}", this.Name, this.Operation, this.Value)); 234 | } 235 | 236 | ResourceObject resource = RmcWrapper.Client.GetResourceByKey(split[0], split[1], split[2], ResourceManagementSchema.GetObjectType(split[0]).Attributes.Select(t => t.SystemName).Except(ResourceManagementSchema.ComputedAttributes)); 237 | 238 | if (resource == null) 239 | { 240 | if (ConfigSyncControl.Preview) 241 | { 242 | return Guid.NewGuid().ToString(); 243 | } 244 | else 245 | { 246 | throw new ArgumentException(string.Format("The attribute operation of {1} on attribute {0} specifies a reference to {2}, but the object was not found in the FIM service", this.Name, this.Operation, value)); 247 | } 248 | } 249 | 250 | return resource.ObjectID.Value; 251 | } 252 | 253 | private string GetXmlReference(string id) 254 | { 255 | ResourceObject resource = this.GetXmlReferenceResource(id); 256 | 257 | return resource.ObjectID == null ? Guid.Empty.ToString() : resource.ObjectID.Value; 258 | } 259 | 260 | private ResourceObject GetXmlReferenceResource(string id) 261 | { 262 | ResourceOperation op = ConfigSyncControl.CurrentConfig.Operations.FirstOrDefault(t => t.ID == id); 263 | 264 | if (op == null) 265 | { 266 | throw new ArgumentException(string.Format("The attribute operation of {1} on attribute {0} specifies a reference to another operation with ID {2}, but the operation was not found in the XML file", this.Name, this.Operation, id)); 267 | } 268 | 269 | if (op.HasProcessed) 270 | { 271 | return op.Resource; 272 | } 273 | 274 | Dictionary anchorValues; 275 | 276 | try 277 | { 278 | anchorValues = op.GetAnchorValues(); 279 | } 280 | catch (Exception ex) 281 | { 282 | throw new ArgumentException(string.Format("The attribute operation of {1} on attribute {0} specifies a reference to another operation with ID {2}, but resource failed to resolve its anchor", this.Name, this.Operation, id), ex); 283 | } 284 | 285 | ResourceObject resource = RmcWrapper.Client.GetResourceByKey(op.ResourceType, anchorValues, op.AttributesToGet); 286 | 287 | if (resource == null) 288 | { 289 | throw new ArgumentException(string.Format("The attribute operation of {1} on attribute {0} specifies a reference to another operation with ID {2}, but the object was not found in the FIM service", this.Name, this.Operation, id)); 290 | } 291 | 292 | return resource; 293 | } 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/XmlConfig/ConfigFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | [XmlRoot(ElementName = "Lithnet.ResourceManagement.ConfigSync")] 10 | public class ConfigFile 11 | { 12 | private Variables variables; 13 | private List operations; 14 | 15 | public Variables Variables 16 | { 17 | get 18 | { 19 | if (this.variables == null) 20 | { 21 | this.variables = new Variables(); 22 | } 23 | 24 | return this.variables; 25 | } 26 | set 27 | { 28 | this.variables = value; 29 | } 30 | } 31 | 32 | [XmlArray(ElementName = "Operations")] 33 | [XmlArrayItem(ElementName = "ResourceOperation", Type = typeof(ResourceOperation))] 34 | public List Operations 35 | { 36 | get 37 | { 38 | if (this.operations == null) 39 | { 40 | this.operations = new List(); 41 | } 42 | 43 | return this.operations; 44 | } 45 | set 46 | { 47 | this.operations = value; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/XmlConfig/ResourceOperation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | using System.Collections.ObjectModel; 7 | using System.Collections; 8 | using Lithnet.ResourceManagement.Client; 9 | using System.Globalization; 10 | 11 | namespace Lithnet.ResourceManagement.Automation 12 | { 13 | public class ResourceOperation 14 | { 15 | public delegate void LogMessageEventHander(object sender, string message); 16 | 17 | internal static event LogMessageEventHander LogEvent; 18 | 19 | private List anchorAttributes; 20 | 21 | private List attributeOperations; 22 | 23 | [XmlArray(ElementName = "AnchorAttributes", IsNullable = true)] 24 | [XmlArrayItem(ElementName = "AnchorAttribute", IsNullable = false)] 25 | public List AnchorAttributes 26 | { 27 | get 28 | { 29 | if (this.anchorAttributes == null) 30 | { 31 | this.anchorAttributes = new List(); 32 | } 33 | 34 | return this.anchorAttributes; 35 | } 36 | set 37 | { 38 | this.anchorAttributes = value; 39 | } 40 | } 41 | 42 | [XmlArray(ElementName = "AttributeOperations", IsNullable = true)] 43 | [XmlArrayItem(ElementName = "AttributeOperation", IsNullable = false)] 44 | public List AttributeOperations 45 | { 46 | get 47 | { 48 | if (this.attributeOperations == null) 49 | { 50 | this.attributeOperations = new List(); 51 | } 52 | 53 | return this.attributeOperations; 54 | } 55 | set 56 | { 57 | this.attributeOperations = value; 58 | } 59 | } 60 | 61 | [XmlAttribute(AttributeName = "operation")] 62 | public ResourceOperationType Operation { get; set; } 63 | 64 | [XmlAttribute(AttributeName = "resourceType")] 65 | public string ResourceType { get; set; } 66 | 67 | [XmlAttribute(AttributeName = "locale")] 68 | public string Locale { get; set; } 69 | 70 | [XmlAttribute(AttributeName = "id")] 71 | public string ID { get; set; } 72 | 73 | [XmlAttribute(AttributeName = "refresh-schema")] 74 | public SchemaRefreshEvent SchemaRefresh { get; set; } 75 | 76 | [XmlIgnore] 77 | public string ObjectID 78 | { 79 | get 80 | { 81 | if (this.Resource != null && this.Resource.ObjectID != null) 82 | { 83 | return this.Resource.ObjectID.Value; 84 | } 85 | else 86 | { 87 | return null; 88 | } 89 | } 90 | } 91 | 92 | [XmlIgnore] 93 | internal bool HasProcessed 94 | { 95 | get 96 | { 97 | return this.Resource != null; 98 | } 99 | } 100 | 101 | [XmlIgnore] 102 | internal ResourceObject Resource { get; private set; } 103 | 104 | internal void ExecuteOperation() 105 | { 106 | if (this.SchemaRefresh == SchemaRefreshEvent.BeforeOperation) 107 | { 108 | this.RaiseLogEvent("Refreshing schema"); 109 | RmcWrapper.Client.RefreshSchema(); 110 | } 111 | 112 | this.ThrowOnLocaleSpecifiedForNonUpdate(); 113 | 114 | switch (this.Operation) 115 | { 116 | case ResourceOperationType.None: 117 | break; 118 | 119 | case ResourceOperationType.Add: 120 | this.ProcessResourceAdd(); 121 | break; 122 | 123 | case ResourceOperationType.Update: 124 | this.ProcessResourceUpdate(); 125 | break; 126 | 127 | case ResourceOperationType.Delete: 128 | this.ProcessResourceDelete(); 129 | break; 130 | 131 | case ResourceOperationType.Add | ResourceOperationType.Update: 132 | this.ProcessResourceAddUpdate(); 133 | break; 134 | 135 | default: 136 | throw new ArgumentException("Unknown or unsupported operation type: " + this.Operation.ToString()); 137 | } 138 | 139 | if (this.SchemaRefresh == SchemaRefreshEvent.AfterOperation) 140 | { 141 | this.RaiseLogEvent("Refreshing schema"); 142 | RmcWrapper.Client.RefreshSchema(); 143 | } 144 | } 145 | 146 | private void ThrowOnLocaleSpecifiedForNonUpdate() 147 | { 148 | if (this.Locale != null) 149 | { 150 | if (this.Operation != ResourceOperationType.Update) 151 | { 152 | throw new InvalidOperationException("Locale can only be specified for an 'Update' operation. Perform an Add-Update first with the invariant culture values, then perform an update with the culture-specific values"); 153 | } 154 | } 155 | } 156 | 157 | private void ProcessResourceAdd() 158 | { 159 | this.Resource = RmcWrapper.Client.CreateResource(this.ResourceType); 160 | this.ExecuteAttributeOperations(); 161 | 162 | this.RaiseLogEvent(string.Format("Creating resource {0} with the following attribute values", this.ID)); 163 | 164 | foreach (AttributeValue attribute in this.Resource.Attributes) 165 | { 166 | this.RaiseLogEvent(string.Format("{0}:{1}", attribute.AttributeName, attribute.ToString())); 167 | } 168 | 169 | if (!ConfigSyncControl.Preview) 170 | { 171 | this.Resource.Save(); 172 | } 173 | } 174 | 175 | private void ProcessResourceUpdate() 176 | { 177 | if (this.Resource == null) 178 | { 179 | CultureInfo locale = null; 180 | 181 | if (!string.IsNullOrWhiteSpace(this.Locale)) 182 | { 183 | locale = new CultureInfo(this.Locale); 184 | } 185 | 186 | this.Resource = RmcWrapper.Client.GetResourceByKey(this.ResourceType, this.GetAnchorValues(), this.AttributesToGet, locale); 187 | 188 | if (this.Resource == null) 189 | { 190 | throw new InvalidOperationException(string.Format("An update operation is not valid for the resource operation with ID {0} as the resource does not exist in the FIM service. Consider changing the operation to an 'Add Update' type", this.ID)); 191 | } 192 | } 193 | 194 | this.ExecuteAttributeOperations(); 195 | 196 | Dictionary> attributeChanges = this.Resource.PendingChanges; 197 | 198 | if (attributeChanges.Count == 0) 199 | { 200 | this.RaiseLogEvent(string.Format("Object {0} was up to date", this.ID)); 201 | } 202 | else 203 | { 204 | this.RaiseLogEvent(string.Format("Updating resource {0} with the following attribute values", this.ID)); 205 | 206 | foreach (KeyValuePair> attributeChange in attributeChanges) 207 | { 208 | foreach (AttributeValueChange valueChange in attributeChange.Value) 209 | { 210 | this.RaiseLogEvent(string.Format("{0}:{1}:{2}", attributeChange.Key, valueChange.ChangeType, valueChange.Value == null ? string.Empty : valueChange.Value.ToString())); 211 | } 212 | } 213 | 214 | if (!ConfigSyncControl.Preview) 215 | { 216 | this.Resource.Save(); 217 | } 218 | } 219 | } 220 | 221 | private void ProcessResourceDelete() 222 | { 223 | if (this.Resource == null) 224 | { 225 | this.Resource = RmcWrapper.Client.GetResourceByKey(this.ResourceType, this.GetAnchorValues(), new List() { "ObjectID" }); 226 | 227 | if (this.Resource == null) 228 | { 229 | this.RaiseLogEvent(string.Format("The object {0} was not found in the FIM service", this.ID)); 230 | return; 231 | } 232 | } 233 | 234 | this.RaiseLogEvent(string.Format("Deleting object {0}-{1}", this.ID, this.ObjectID)); 235 | 236 | if (!ConfigSyncControl.Preview) 237 | { 238 | RmcWrapper.Client.DeleteResource(this.Resource); 239 | } 240 | } 241 | 242 | private void ProcessResourceAddUpdate() 243 | { 244 | this.Resource = RmcWrapper.Client.GetResourceByKey(this.ResourceType, this.GetAnchorValues(), this.AttributesToGet); 245 | 246 | if (this.Resource == null) 247 | { 248 | this.ProcessResourceAdd(); 249 | } 250 | else 251 | { 252 | this.ProcessResourceUpdate(); 253 | } 254 | } 255 | 256 | internal Dictionary GetAnchorValues() 257 | { 258 | Dictionary anchors = new Dictionary(); 259 | 260 | foreach (string anchor in this.AnchorAttributes) 261 | { 262 | if (string.IsNullOrWhiteSpace(anchor)) 263 | { 264 | throw new ArgumentException(string.Format("The resource operation with ID {0} specified a modification type that requires an anchor, but no anchor attributes were present")); 265 | } 266 | 267 | AttributeOperation attributeOp = this.AttributeOperations.FirstOrDefault(t => t.Name == anchor); 268 | 269 | if (attributeOp == null) 270 | { 271 | throw new ArgumentException( 272 | string.Format( 273 | "The resource operation with ID {0} specified a modification type that requires an anchor, but the defined anchor attribute was not present in the list of AttributeOperations", 274 | this.ID)); 275 | } 276 | 277 | anchors.Add(anchor, attributeOp.ExpandedValue.ToString()); 278 | } 279 | 280 | return anchors; 281 | } 282 | 283 | internal IEnumerable AttributesToGet 284 | { 285 | get 286 | { 287 | List attributesToGet = new List(); 288 | 289 | foreach (string anchor in this.AnchorAttributes) 290 | { 291 | attributesToGet.Add(anchor); 292 | } 293 | 294 | foreach (AttributeOperation op in this.AttributeOperations) 295 | { 296 | attributesToGet.Add(op.Name); 297 | } 298 | 299 | return attributesToGet.Distinct(); 300 | } 301 | } 302 | 303 | private void ExecuteAttributeOperations() 304 | { 305 | foreach (AttributeOperation op in this.AttributeOperations) 306 | { 307 | op.ExecuteOperation(this.Resource, this.Operation); 308 | } 309 | } 310 | 311 | private void RaiseLogEvent(string message) 312 | { 313 | if (ResourceOperation.LogEvent != null) 314 | { 315 | ResourceOperation.LogEvent(this, message); 316 | } 317 | } 318 | } 319 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/XmlConfig/Variable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | 7 | namespace Lithnet.ResourceManagement.Automation 8 | { 9 | public class Variable 10 | { 11 | [XmlAttribute("name")] 12 | public string Name { get; set; } 13 | 14 | [XmlAttribute("value")] 15 | public string Value { get; set; } 16 | 17 | [XmlIgnore] 18 | public string ExpandedValue 19 | { 20 | get 21 | { 22 | return Environment.ExpandEnvironmentVariables(this.Value); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/XmlConfig/Variables.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | using System.IO; 7 | using System.Xml; 8 | using System.Collections; 9 | 10 | namespace Lithnet.ResourceManagement.Automation 11 | { 12 | [XmlRoot(ElementName = "Lithnet.ResourceManagement.ConfigSync.Variables")] 13 | [XmlType("Variables")] 14 | public class Variables 15 | { 16 | [XmlAttribute("import-file")] 17 | public string FileName { get; set; } 18 | 19 | [XmlElement("Variable")] 20 | public List Items { get; set; } 21 | 22 | internal void LoadFileVariables(string currentPath) 23 | { 24 | if (!string.IsNullOrWhiteSpace(this.FileName)) 25 | { 26 | XmlSerializer s = new XmlSerializer(typeof(Variables)); 27 | 28 | string filename; 29 | 30 | if (Path.IsPathRooted(this.FileName)) 31 | { 32 | filename = this.FileName; 33 | } 34 | else 35 | { 36 | filename = Path.Combine(currentPath, this.FileName); 37 | } 38 | 39 | StreamReader sr = File.OpenText(filename); 40 | XmlReader xr = XmlReader.Create(sr); 41 | Variables variables = (Variables)s.Deserialize(xr); 42 | 43 | variables.LoadFileVariables(currentPath); 44 | 45 | foreach (Variable variable in variables.Items) 46 | { 47 | this.Items.Add(variable); 48 | } 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Automation/packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Resolver/Lithnet.ResourceManagement.Resolver.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D93AB9DD-9953-4E78-B247-DD5C89097844} 8 | Library 9 | Properties 10 | Lithnet.ResourceManagement.Resolver 11 | Lithnet.ResourceManagement.Resolver 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | C:\Windows\Sysnative\WindowsPowerShell\v1.0\Modules\LithnetRMA\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 53 | -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Resolver/MrmResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Reflection; 6 | 7 | namespace Lithnet.ResourceManagement.Resolver 8 | { 9 | public static class MrmResolver 10 | { 11 | private static int loadAttempts; 12 | 13 | public static void RegisterResolver() 14 | { 15 | AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 16 | } 17 | 18 | private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 19 | { 20 | if (args.Name.StartsWith("Microsoft.ResourceManagement")) 21 | { 22 | loadAttempts++; 23 | 24 | if (loadAttempts > 1) 25 | { 26 | return null; 27 | } 28 | 29 | try 30 | { 31 | #pragma warning disable 618 32 | return Assembly.LoadWithPartialName("Microsoft.ResourceManagement"); 33 | #pragma warning restore 618 34 | } 35 | catch 36 | { 37 | try 38 | { 39 | return Assembly.Load("Microsoft.ResourceManagement.dll"); 40 | } 41 | catch 42 | { 43 | } 44 | } 45 | 46 | } 47 | 48 | return null; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/Lithnet.ResourceManagement.Resolver/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Lithnet.ResourceManagement.Resolver")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Lithnet.ResourceManagement.Resolver")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fb9c8b6c-aeab-48ce-8aef-dbdc61a959b8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | --------------------------------------------------------------------------------