Create Nuget Pacakge with configuration of cloud config(ServiceDefinition.csdef) file - azure

I would like to build Nuget package for my add-on which will be used by end user to install as startup task and after that they will upload their applications on window azure platform.
Let's take one simple web application and one cloud project now using Nuget end user will added add-on package it will add 2 files(exe & config) in web application project & add startup task to ServiceDefinition.csdef of cloud project as per shown in figure
How can i created this type of Nuget Pacakge?
Thanks in advance.
Update:
I have tried according with NICK's answer however i am getting problem with 2 webrole in cloud project according to shown in below fig.
and error i am getting as per below
Also i have one question that If i am installing that Nuget package with command line then how i can consider all webrole projects to add exe and config file in solution??

Nuget packages work based on a convention:
http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#From_a_convention_based_working_directory
As far as the exe and config you can do the following:
In your package directory make the following directories
mkdir lib (for the exe)
mkdir content (for the config)
All you have to do for the exe is drop the file in the lib directory and modify you .nuspec file just under the metadata node. There should be a "files" node (if not you can add one). Add something like this inside the files node:
<file src="content\my.exe" target="content\my.exe" />
The config is a little different. Just add a file named myname.config.transform to the content directory and add an entry into the .nuspec file:
A couple of things to note:
If the config file does not exist in your app it will add one for you.
You only have to add the nodes you want transformed if there is a file that already exists
The transform file will do a complete match on your node so if the following existed in
your config file:
<add key="test" value="myval"/>
And in your transform you had:
<add key="test" value="myval2"/>
The resulting file would look like:
<add key="test" value="myval"/>
<add key="test" value="myval2"/>
As far as adding the startup task, that's been a little more tricky for me (there might be a much better way). I use powershell in the install.ps1 (just like the files above but you create a "tools" directory for it):
param($installPath, $toolsPath, $package, $project)
#Modify the service config - adding a new Startup task
$svcConfigFile = $DTE.Solution.Projects|Select-Object -Expand ProjectItems|Where-Object{$_.Name -eq 'ServiceDefinition.csdef'}
$ServiceDefinitionConfig = $svcConfigFile.Properties.Item("FullPath").Value
[xml] $xml = gc $ServiceDefinitionConfig
#Create startup and task nodes
# So that you dont get the blank ns in your node
$startupNode = $xml.CreateElement('Startup','http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition')
$taskNode = $xml.CreateElement('Task','http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition')
$taskNode.SetAttribute('commandLine','my.exe')
$taskNode.SetAttribute('executionContext','elevated')
$taskNode.SetAttribute('taskType','simple')
$startupNode.AppendChild($taskNode)
#Check to see if the startup node exists
$modified = $xml.ServiceDefinition.WebRole.StartUp
if($modified -eq $null){
$modified = $xml.ServiceDefinition.WebRole
$modified.PrependChild($startupNode)
}
else{
$nodeExists = $false
foreach ($i in $xml.ServiceDefinition.WebRole.Startup.Task){
if ($i.commandLine -eq 'my.exe'){
$nodeExists = $true
}
}
if($taskNode -eq $null -and !$nodeExists){
$modified.AppendChild($taskNode)
}
}
$xml.Save($ServiceDefinitionConfig);
I hope this helps out.
--Nick

Related

Azure function app, Powershell 7.2 dll module install

I have this powershell script which works very well on my computer. I use the x64 and powershell 7.2.
The problem is when I publish the code to Azure, there is a module missing. The module is a .net System.Data.OleDb.
ERROR: Exception calling "Open" with "0" argument(s): "The 'MSOLAP' provider is not registered on the local machine."
I have tried to add the .dll file to Module folder, that i created but function app doesn't load it for some reason.
Structure of the function app
host.json
local.settings.json
powerbitablerefresh
run.ps1
function.json
Modules
Microsoft.AnalysisServices.AzureClient.dll
profile.ps1
requirements.psd1
inside requirements I have:
'Az.Keyvault' = '4.*'
'Az.Accounts' = '2.*'
'Az.AnalysisServices' = '1.*'
'SqlServer' = '21.1.18256'
My question is, how do I install .dll on a function app?
how do I install .dll on a function app?
You can install .dll files by following below workaround:
Firstly, Login to Azure
Then open your Function App
Then Click on Advanced tools , then click on Go
Then Click on Tools, Then click on Zip Push Depoly like below:
Then Click on your function app
Then click on bin folder and after it opens, drag your .dll file over there and then you can reference them in your function app:
The right answer is that add the .dll files to the C:\home\site\wwwroot\ and then in the powershell script run it like this
Add-Type -Path (Join-Path $PSScriptRoot "Microsoft.Identity.Client.dll")
Add-Type -Path (Join-Path $PSScriptRoot "Microsoft.AnalysisServices.AdomdClient.dll")
It will then create a connection

java.io.FileNotFoundException: Resource not found: /credentials.json on Java QuickStart for Classroom API

I have implemented the Java QuickStart for the Classroom API and am getting an error message "java.io.FileNotFoundException: Resource not found: /credentials.json" at run-time. I copied my credentials.json file to the Project res directory, but continue to get this error. Any suggestions?
I tried it in a different way than I found on other websites, and it worked for me.
replace below code:
InputStream in = GoogleSheetAPIHandler.class.getClass().getResourceAsStream(CREDENTIALS_FILE_PATH);
With this code:
InputStream in = new FileInputStream(CREDENTIALS_FILE_PATH);
You need to import credential.json file into the src/main/resources folder in eclipse. You may be included in the project folder. But you need to import it into eclipse.
locate your credentials.json file in the folder.
click and drag it
drop it in src/main/resource and click ok.
After importing into eclipse it should show like the below image.
There are two steps needed to find the resource in Eclipse:
To have the file in the resources folder
Create the resource folder (if it does not exist): src/main/resouces
Add the credential file to the resource folder: src/main/resouces/credential.json
To have the resources folder in the Source Java Build Path
Go to Eclipse Path Source: Project > Properties > Java Build Path > Source (tab)
Add resources folder: Add Folder ... (button) > resources (check box) > OK (button)
https://stackoverflow.com/a/46950488/10850340
The name of your file has to be credentials only, if you have credentials.json as the name of your file in your folder you will get this error.

Cannot run PowerShell scripts in Azure Functions v2

I'm trying to write a Function App using .NET Core in Azure Functions v2. When using the Microsoft.Powershell.SDK package from Nuget (required for .NET Core PowerShell runtime) I cannot get Visual Studio to copy the System.Management.Automation library to the bin with my Function App.
This results in the following error:
System.Private.CoreLib: Exception while executing function: Function1. TestPowershellInFunction: Could not load file or assembly 'System.Management.Automation, Version=6.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified. System.Private.CoreLib: Could not load the specified file.
I've reproduced this in an existing Azure Function and a new Solution by simply creating a Timer function and adding the following snippet:
PowerShell shell = PowerShell.Create();
IEnumerable<PSObject> result = shell.AddScript("Write-Output 'Hello, World!'").Invoke();
foreach(PSObject line in result)
{
log.LogInformation(line.ToString());
}
This works on a new Console App with the PowerShell Nuget installed, but when added to the Function App I get the error. I do notice that System.Management.Automation doesn't get put in the bin directory with a regular Console App but I'm not sure how to interpret this. I know it's a System library but I can't use it unless the Nuget is installed, so I don't know if this is a special case. In both scenarios I'm using v6.1.1 of the PowerShell Nuget.
Is this a known bug with Functions v2? Or am I missing something?
It's a known issue that Function can't load runtime assemblies([FunctionProject]\bin\Debug\netcoreapp2.1\bin\runtimes) correctly.
The workaround is to move assemblies to output dir bin manually. Right click on your function project and Edit <FunctionProject>.csproj. Add following items to achieve our goal.
<PropertyGroup>
<SDKVersion>6.1.1</SDKVersion>
<SDKPlatform>win-x86</SDKPlatform>
</PropertyGroup>
<ItemGroup>
<None Include="
$(USERPROFILE)\.nuget\packages\system.directoryservices\4.5.0\runtimes\win\lib\netcoreapp2.0\System.DirectoryServices.dll;
$(USERPROFILE)\.nuget\packages\system.management\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Management.dll;
$(USERPROFILE)\.nuget\packages\system.management.automation\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\System.Management.Automation.dll;
$(USERPROFILE)\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes\win10-x86\lib\netstandard1.6\Microsoft.Management.Infrastructure.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Management.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.utility\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Utility.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.diagnostics\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Diagnostics.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.sdk\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.SDK.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.security\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Security.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.coreclr.eventing\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.CoreCLR.Eventing.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.consolehost\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.ConsoleHost.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.markdownrender\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.MarkdownRender.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.runtime\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Runtime.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Management.dll;
">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="CopyRuntimeToBin" AfterTargets="Build">
<Copy SourceFiles="
$(USERPROFILE)\.nuget\packages\system.directoryservices\4.5.0\runtimes\win\lib\netcoreapp2.0\System.DirectoryServices.dll;
$(USERPROFILE)\.nuget\packages\system.management\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Management.dll;
$(USERPROFILE)\.nuget\packages\system.management.automation\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\System.Management.Automation.dll;
$(USERPROFILE)\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes\win10-x86\lib\netstandard1.6\Microsoft.Management.Infrastructure.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Management.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.utility\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Utility.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.diagnostics\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Diagnostics.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.sdk\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.SDK.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.security\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Security.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.coreclr.eventing\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.CoreCLR.Eventing.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.consolehost\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.ConsoleHost.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.markdownrender\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.MarkdownRender.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.runtime\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Runtime.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Management.dll;
" DestinationFolder="$(OutputPath)\bin" />
</Target>
Note that microsoft.management.infrastructure is set to win10-x86 on my side(Win10), you may need to change according to your pc platform. Assemblies are x86 as VS uses x86 Function CLi by default, we don't need to worry about it unless we need to work with x64.

Windows azure project replace ServiceConfiguration.Cloud.cscfg

I have two MVC projects. And I created two WindowsAzure project:WindowsAzure1-> which package MVC1 , and WindowsAzure2-> which package MVC2 project. After CheckIn on Local TFS 2012, I build my solution. MSBuild Arguments:
/t:Publish /p:PublishDir=c:\drops\app.publish\
After Build I see 3 file, instead 4.
1.WindowsAzure1.cspkg
2.WindowsAzure2.cspkg
3.ServiceConfiguration.Cloud.cscfg//It contain config WindowsAzure2.cspkg
I tried to rename ServiceConfiguration.Cloud.cscfg, but it doesn't rename.
So, I think the better place package on different folder. But problem that in the future MVC and Azure project will be unknown count. So I need automatically create folder contains name project. So how can it do?
Simple Way to create dynamic folders is through PowerShell Script.
Lets say you have folder structure of projects in following way -
Then you can following script to generate package folders -
# Solution directory, which contains all the projects
$path = "C:\Solution"
$folders = Get-ChildItem -Path $path
foreach ($folder in $folders)
{
if ($folder.Attributes -eq "Directory")
{
if($folder.Name -like "*.Cloud")
{
New-Item -Path "$($path)\$($folder.Name)package" -ItemType "Directory"
}
}
}
Output will be -
Then you can use CSPack utility and PowerShell combination to create package and save configuration file to the location of your interest.
http://www.intstrings.com/ramivemula/articles/jumpstart-30-create-azure-cloud-service-package-cspkg-of-visual-studio-2013-project-solution-using-powershell/

Assembly Versioning using CruiseControl.net

I have setup CruiseControl.net for a bunch of my projects which are related.
As a result a single project tag in CruiseControl has multiple SVN checkouts and then a bunch of msbuild tasks compile all the individual sln files.
I need to update the assembly version of all the solutions when this build is being done.
However, since i'm not using nant and not using MSBuild proj files, I am unsure on how to get this.
I wonder if I'm missing something obvious. I just need a solution which can be implemented by making appropriate changes in the ccnet.config file without requiring me to make changes to csproj files.
Thanks,
Anj
What about using a shared AssemblyInfo across your projects?
This is what we do for our products:
Each project has it's own AssemblyInfo.cs - this contains AssemblyTitle, AssemblyDescription, Guid, and other attributes that are unique to that assembly.
Each project also has two other Assembly Info files, note that these are added as a link rather than a direct file (VS -> Add -> Existing File -> Add as link (little down arrow next to add))
The two link files:
CompanyAssemblyInfo.cs - AssemblyCompany, AssemblyCopyright, AssemblyConfiguration, CLSCompliant, SecurityPermission, etc. Basically everything we want standard on all our assemblies.
ProductAssemblyInfo.cs - AssemblyProduct, AssemblyVersion, AssemblyFileVersion. This allows us to push the same version across to all assemblies from the one file.
Our CI and release process is more complicated, but that's at the heart of it - a single point (file) which controls the product version (assemblies, installers, everything!)
There's a task to do just what you're asking about.
You'll need to install the MSBuildCommunity tasks, found here.
Then, you can create something like this:
<PropertyGroup>
<MyAssemblyVersion>$(CCNetLabel)</MyAssemblyVersion>
</PropertyGroup>
<Target Name="GenAssemblyInfo">
<AssemblyInfo
ContinueOnError="false"
CodeLanguage="CS"
OutputFile="$(MSBuildProjectDirectory)\YourAssembly\AssemblyInfo.cs"
AssemblyTitle="blah"
AssemblyDescription="blah blah"
AssemblyCompany="Anj Software, Inc."
AssemblyProduct="Anj's Awesome App"
AssemblyCopyright="blah blah"
CLSCompliant="false"
AssemblyVersion="$(MyAssemblyVersion)"
AssemblyFileVersion="$(MyAssemblyVersion)"
/>
</Target>
Note that you can set a build number prefix in your ccnet.config file so that your assemblies will be numbered 2.1.0.x where x is the build number. That's how we do our version numbering where I work.
You'll still need to keep a default AssemblyInfo.cs file as part of each of the projects that make up your solution.
I use powershell for this. lpath is the path to the source code, and buildnum is my buildnumber I append. That is all I actually do with this. However, it should give you enough to change or set any or all of the other fields available. I pass in lpath and I get the buildnumber from the available environment variables in CC.NET and I can use this script over and over again, just changing what I pass in on the command line in the config file. I also have one that modifies the resource files for the C++ Code if that is actually what you need to modify.
$files = Get-ChildItem $lpath -recurse -filter *AssemblyInfo.cs -name
Foreach ($file in $files)
{
$file = $lpath + "\" + $file
$fileObject=get-item $file
$fileObject.Set_IsReadOnly($False)
$sr = new-object System.IO.StreamReader( $file, [System.Text.Encoding]::GetEncoding("utf-8") )
$content = $sr.ReadToEnd()
$sr.Close()
$content = [Regex]::Replace( $content, '(?<=\[assembly: AssemblyVersion\("[0-9].[0-9].[0-9].)[0-9]?[0-9]?[0-9]', $buildnum);
$content = [Regex]::Replace( $content, '(?<=\[assembly: AssemblyFileVersion\("[0-9].[0-9].[0-9].)[0-9]?[0-9]?[0-9]', $buildnum);
$sw = new-object System.IO.StreamWriter( $file, $false, [System.Text.Encoding]::GetEncoding("utf-8") )
$sw.Write( $content )
$sw.Close()
$fileObject.Set_IsReadOnly($True)
}

Resources