How to create transform for .msi file using c# - c#

I'm trying to create a transform for .msi file in C#. Here is my code:
public static void CreateTransforms(string original_MSI, string backup_MSI, string MSTpath, string query)
{
File.Copy(original_MSI, backup_MSI, true);
using (var origDatabase = new Microsoft.Deployment.WindowsInstaller.Database(original_MSI, DatabaseOpenMode.ReadOnly))
{
using (var database = new Microsoft.Deployment.WindowsInstaller.Database(backup_MSI, DatabaseOpenMode.Direct))
{
//database.Execute("Update `Property` Set `Property`.`Value` = 'Test' WHERE `Property`.`Property` = 'ProductName'");
database.Execute(query);
database.GenerateTransform(origDatabase, MSTpath);
database.CreateTransformSummaryInfo(origDatabase, MSTpath, TransformErrors.None, TransformValidations.None);
}
}
}
I got the following error : "This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package." in the step create transform summary info. I used "Microsoft.Deployment.WindowsInstaller.dll" library. Any help would be great.

A quick read of this static method looked correct so I created a console app out of it. It works fine for me on my machine. I would look at your calling method and make sure the data being passed is correct. I get really nervous any time I have a method that takes 4 strings as arguments as that leaves a lot to desire in terms of type safety.

when CreateTransforms start, it open database and it does not close it ...
you must commit and close the database before apply a new transform!
database.GenerateTransform(origDatabase, TRANSFORM);
database.CreateTransformSummaryInfo(origDatabase, TRANSFORM, TransformErrors.None, TransformValidations.None);
database.Commit();
database.Close();

Related

How to use Google Cloud Speech (V1 API) for speech to text - need to be able to process over 3 hours audio files properly and efficiently

I am looking for documentation and stuff but could not find a solution yet
Installed NuGet package
Also generated API key
However can't find proper documentation how to use API key
Moreover, I want to be able to upload very long audio files
So what would be the proper way to upload up to 3 hours audio files and get their results?
I have 300$ budget so should be enough
Here my so far code
This code currently fails since I have not set the credentials correctly at the moment which I don't know how to
I also have service account file ready to use
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var speech = SpeechClient.Create();
var config = new RecognitionConfig
{
Encoding = RecognitionConfig.Types.AudioEncoding.Flac,
SampleRateHertz = 48000,
LanguageCode = LanguageCodes.English.UnitedStates
};
var audio = RecognitionAudio.FromStorageUri("1m.flac");
var response = speech.Recognize(config, audio);
foreach (var result in response.Results)
{
foreach (var alternative in result.Alternatives)
{
Debug.WriteLine(alternative.Transcript);
}
}
}
}
I don't want to set environment variable. I have both API key and Service Account json file. How can I manually set?
You need to use the SpeechClientBuilder to create a SpeechClient with custom credentials, if you don't want to use the environment variable. Assuming you've got a service account file somewhere, change this:
var speech = SpeechClient.Create();
to this:
var speech = new SpeechClientBuilder
{
CredentialsPath = "/path/to/your/file"
}.Build();
Note that to perform a long-running recognition operation, you should also use the LongRunningRecognize method - I strongly suspect your current RPC will fail, either explicitly because it's trying to run on a file that's too large, or it'll just time out.
You need to set the environment variable before create the instance of Speech:
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "text-tospeech.json");
Where the second param (text-tospeech.json) is your file with credentials generated by Google Api.

Sparx EA .feap projects images saved as blank

In addin for Sparx EA I use this code to get pictures and assign to entity. Then I use images from entities, to, as example, save at some folders or insert in word report etc (from this answer)
/// <summary>
/// Access to diagram image without using clipboard
/// </summary>
/// <param name="projectInterface">Ea Sparx interface</param>
/// <param name="eaDiagramGuid">Guid of the diagramm</param>
/// <returns></returns>
public static Image GetDiagramImage(this Project projectInterface, Guid eaDiagramGuid, ApplicationLogger _logger)
{
Image diagramImage;
try
{
var diagramByGuid = projectInterface.GUIDtoXML(eaDiagramGuid.ToString("B"));
string tempFilename = string.Format("{0}{1}{2}", Path.GetTempPath(), Guid.NewGuid().ToString(), ".png");
bool imageToFileSuccess = projectInterface.PutDiagramImageToFile(diagramByGuid, tempFilename, FileExtensionByName);
if (imageToFileSuccess)
{
using (var imageStream = new MemoryStream(File.ReadAllBytes(tempFilename)))
{
diagramImage = Image.FromStream(imageStream);
}
File.Delete(tempFilename);
}
else
{
throw new Exception(string.Format("Image to file exprot fail {0}", projectInterface.GetLastError()));
}
}
catch (Exception e)
{
throw;
}
return diagramImage;
}
The problem is - it works if project I work with saved as .eap file.
If it's .feap file, which, as I believe means that it works with Firebird database (instead of Access), all saved/exproted to report images are blank, like this down below
Why does it happens and is there workaround?
UPD
It works if I use projectInterface.PutDiagramImageOnClipboard instead but I don't wont to use clipboard at all
UPD 2
After some experiments today at the morning (at my timezone, gmt+3, it's still morning) I found out that the problem was with GUIDs register!
After I decided to apply .toUpper() here
var diagramByGuid = projectInterface.GUIDtoXML(eaDiagramGuid.ToString("B").ToUpper());
it started work fine!
Strange thing thou that if project is *.EAP type everything works even when guid is not in upper register!
UPD3
Well, unfortunately, I was wrong. Some pictures are still blank. But somehow that changes got impact on diagrams, I keep testing this stuff.
And some of the pictures are appeared twice or in wrong place.
But it's kinda interesting (if I could say so) behaviour.
UPD 4
I was wrong in my UPD2 part! GUID can contain down register symbols as well as upper ones.
So, first I removed that part.
What I done next - I started to pass GUID directly from diagram, so signature changed like that
public static Image GetDiagramImage(this Project projectInterface, string eaDiagramGuid, ApplicationLogger _logger)
and eaDiagramGuid should be passed right from EA.Diagram object.
When we parse it as Guid by Guid.Parse(eaDiagramGuid) it convert everything in lowercase like here
so, thats why I got the problem.
But for some reason it was not appeared in *.EAP type of projects!
Also it strange that register matters in that case, really. Seems like GUID in common and GUID in sparx ea are different things!
Okay, as I founded out here, the thing is, in case of *.FEAP all items GUIDs are surprisingly case sensetive.
So, my mistake was to store item GUID as Guid type - when we use Guid.Parse(myGuidString) function and then we converting it back to string - all symbols are appers to be in lowercase.
Also, I got my answer from support (they were surprisingly fast, I really like that)
Hello Danil,
Running over the Stack Overflow - it sounds like it's effectively
answered. The core point is that the Feap files are case sensitive.
To be technical, the collation used for our Firebird databases is case
sensitive.
So, in the Automation script you do need to adhere to the case.
So, I just change things to work directly with GUID string from project item like
Image diagramImage = _eaProjectInterface.GetDiagramImage(diagram.DiagramGUID, _logger);
and function now look like this
public static Image GetDiagramImage(this Project projectInterface, string eaDiagramGuid, ApplicationLogger _logger)
{
Image diagramImage;
try
{
var diagramByGuid = projectInterface.GUIDtoXML(eaDiagramGuid);
string tempFilename = string.Format("{0}{1}{2}", Path.GetTempPath(), Guid.NewGuid().ToString(), ".png");
bool imageToFileSuccess = projectInterface.PutDiagramImageToFile(diagramByGuid, tempFilename, FileExtensionByName);
if (imageToFileSuccess)
{
using (var imageStream = new MemoryStream(File.ReadAllBytes(tempFilename)))
{
diagramImage = Image.FromStream(imageStream);
}
File.Delete(tempFilename);
}
else
{
throw new Exception(string.Format("Image to file exprot fail {0}", projectInterface.GetLastError()));
}
}
catch (Exception e)
{
throw;
}
return diagramImage;
}
So, this means that Sparx EA *.FEAP project GUIDs are NOT really GUIDs but just string-keys (as I assume).
Be careful when your work with them :-)

Update Data Source and DataSet reference for SSRS 2012 Deployment from C#

EDIT: I think I can simplify this question a bit to ask for only what is needed to know:
I am working with C# using the SSRS 2010 Web Service:
'ReportService2010.asmx' http://technet.microsoft.com/en-us/library/ee640743.aspx
I can use the method 'CreateDataSource' to create a Datasource on an instance of an SSRS Server http:// (servername)/ReportServer.
I can also use the method 'CreateCatalogItem' to create a report on a server from referencing a project's RDL local file to serialize it to a byte array and then pass that as a 'Definition' to the method to create it on the server.
Now everything I do works with a caveat, and a major one. I can only deploy everything to the same folder. If I deploy a Data Source to say the 'Data Sources' folder and then a report to say: 'Test Reports', the report does not know it has a shared data source to reference at a different location. So I dug a little at the technet articles and have tried to 'GetItemDataSources' method but it only gives a name and a type for the ReportingService2010.DataSource return type. Does anyone know the method to link up a 'Report' or 'Dataset's CatalogItem property of 'DataSource', so it points to a reference in a different folder on the SSRS Server when deploying? There has to be a way to do it as I know I can deploy from Business Intelligence Development Studio and it can do this.
I've had similar issues when deploying report files; when deploying through rs.exe or code you run into these issues where reports lose their link to a Data Source.
We solved this by explicitly pointing the report to the server-side Data Source immediately after being deployed by our application; is this similar to what you're trying to do?
Anyway, here's the slightly adapted code we use in our report deployment application:
static void SetReportDataSource(string reportPath)
{
string dsPath = CombinePath(DataSourcePath, DataSourceFolder, DataSourceName);
DataSourceReference dsRef = new DataSourceReference()
{
Reference = dsPath
};
DataSource ds = new DataSource();
ds.Item = dsRef as DataSourceDefinitionOrReference;
ds.Name = DataSourceName;
var rptDataSources = Server.GetItemDataSources(reportPath);
foreach (var rptDs in rptDataSources)
{
Server.SetItemDataSources(filePath, new DataSource[] { ds });
}
}
So, basically we have variables that define information like the Data Source name, Data Source location on server, and the same for a report. They can be in different folders.
Based on this, we create a new reference to a Data Source and then repoint the report to this using SetItemDataSources.
This sorted out the Data Source issue for me, anyway. Not sure about Shared Datasets and how they handle all of this, but hopefully this will be of some help.
Also, just thought that this would be using the ReportService2005 endpoint, but it's probably not too different for ReportService2010.
Edit:
For the paths mentioned here, these are relative to the server, e.g. /Reports/. You don't need the fully qualified name as you define the Url property of the ReportService2010 object which contains the destination.
Maybe this might be some help. I used it to reset the DataSource for all the reports in a given Parent Folder, and it's subfolders:
using System;
using GetPropertiesSample.ReportService2010;
using System.Diagnostics;
using System.Collections.Generic; //<== required for LISTS
using System.Reflection;
namespace GetPropertiesSample
{
class Program
{
static void Main(string[] args)
{
GetListOfObjectsInGivenFolder_and_ResetTheReportDataSource("0_Contacts"); //<=== This is the parent folder
}
private static void GetListOfObjectsInGivenFolder_and_ResetTheReportDataSource(string sParentFolder)
{
// Create a Web service proxy object and set credentials
ReportingService2010 rs = new ReportingService2010();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
CatalogItem[] reportList = rs.ListChildren(#"/" + sParentFolder, true);
int iCounter = 0;
foreach (CatalogItem item in reportList)
{
iCounter += 1;
Debug.Print(iCounter.ToString() + "]#########################################");
if (item.TypeName == "Report")
{
Debug.Print("Report: " + item.Name);
ResetTheDataSource_for_a_Report(item.Path, "/DataSources/Shared_New"); //<=== This is the DataSource that I want them to use
}
}
}
private static void ResetTheDataSource_for_a_Report(string sPathAndFileNameOfTheReport, string sPathAndFileNameForDataSource)
{
//from: http://stackoverflow.com/questions/13144604/ssrs-reportingservice2010-change-embedded-datasource-to-shared-datasource
ReportingService2010 rs = new ReportingService2010();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
string reportPathAndName = sPathAndFileNameOfTheReport;
//example of sPathAndFileNameOfTheReport "/0_Contacts/207_Practices_County_CareManager_Role_ContactInfo";
List<ReportService2010.ItemReference> itemRefs = new List<ReportService2010.ItemReference>();
ReportService2010.DataSource[] itemDataSources = rs.GetItemDataSources(reportPathAndName);
foreach (ReportService2010.DataSource itemDataSource in itemDataSources)
{
ReportService2010.ItemReference itemRef = new ReportService2010.ItemReference();
itemRef.Name = itemDataSource.Name;
//example of DataSource i.e. 'itemRef.Reference': "/DataSources/SharedDataSource_DB2_CRM";
itemRef.Reference = sPathAndFileNameForDataSource;
itemRefs.Add(itemRef);
}
rs.SetItemReferences(reportPathAndName, itemRefs.ToArray());
}
}
}

Can i Read code from a file and and let that code run in an application

I am developing an Desktop Application in WPF using C# .
For the sake of simplicity, Assume my Application has functions which draw lines in said direction goleft() , goright() , goforward() , goback() .
when any of these function is called a line of one inch will be drawn on screen.
I want to make application where user will write code in a file in any editor (say notepad) and save that file in some fixed format (say .abc or .xyz)
Imaginary Example :
(section_start)
For(int i = 0 ; i<= 20 ; i++ )
{
if(i<5)
goforward();
else if(i==5)
goleft();
else if(i < 10)
forward();
.......
........
}
(section_End)
Can i make application which should be capable of reading this file and execute code which is written in between of (section_start) and (section_End). and only if possible can check for syntax errors too... (Not compulsory).
Please guide me on this issue :
Disclosure : My actual Application is somewhat else and could not discuss here due to my company's rules.
Thanks to all who replied to my question. Stackoverflow is fantastic site , i have found the roadmap where to go , till today morning i did not have any clue but now i can go ahead , thanks all of you once again
Will ask question again if i get stucked somewhere
You can read the file content using FileInfo and get the code you need to execute.
Then you can execute the code using CSharpCodeProvider like in this post:
using (Microsoft.CSharp.CSharpCodeProvider foo =
new Microsoft.CSharp.CSharpCodeProvider())
{
var res = foo.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = true
},
"public class FooClass { public string Execute() { return \"output!\";}}"
);
var type = res.CompiledAssembly.GetType("FooClass");
var obj = Activator.CreateInstance(type);
var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}
You can choose CodeDOM or IL Emit
More help on CodeDOM
More information on IL Generator / Emit
This is called scripting your application if I understand correctly. C# does not support this out of the box. One thing to look into could be the new Roselyn compiler from Microsoft (it is a new take on the C# compiler, which lets you do just this).
For more info on Roselyn check out:
http://blogs.msdn.com/b/csharpfaq/archive/2011/12/02/introduction-to-the-roslyn-scripting-api.aspx
I've only seen a demo of it, but it looks very promissing, and should solve your problem.
It's not clear what kind of code you want compiled but here is a guide on how to compile code code with C#.
You could use IronPython to handle the script.
Here's an example of how to do this:
First you need a navigation object to perform the operations on:
public class NavigationObject
{
public int Offset { get; private set; }
public void GoForwards()
{
Offset++;
}
public void GoBackwards()
{
Offset--;
}
}
Then the code to execute the file:
public void RunNavigationScript(string filePath, NavigationObject navObject)
{
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
scope.SetVariable("navigation", navObject);
var source = engine.CreateScriptSourceFromFile(filePath);
try
{
source.Execute(scope);
}
catch(Exception
{
}
}
The script file can then take the form of something like:
for x in range(0,20):
if x == 5:
navigation.GoBackwards()
else:
navigation.GoForwards()

How to access WinRM in C#

I'd like to create a small application that can collect system information (Win32_blablabla) using WinRM as opposed to WMI. How can i do that from C#?
The main goal is to use WS-Man (WinRm) as opposed to DCOM (WMI).
I guess the easiest way would be to use WSMAN automation. Reference wsmauto.dll from windwos\system32 in your project:
then, code below should work for you. API description is here: msdn: WinRM C++ API
IWSMan wsman = new WSManClass();
IWSManConnectionOptions options = (IWSManConnectionOptions)wsman.CreateConnectionOptions();
if (options != null)
{
try
{
// options.UserName = ???;
// options.Password = ???;
IWSManSession session = (IWSManSession)wsman.CreateSession("http://<your_server_name>/wsman", 0, options);
if (session != null)
{
try
{
// retrieve the Win32_Service xml representation
var reply = session.Get("http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service?Name=winmgmt", 0);
// parse xml and dump service name and description
var doc = new XmlDocument();
doc.LoadXml(reply);
foreach (var elementName in new string[] { "p:Caption", "p:Description" })
{
var node = doc.GetElementsByTagName(elementName)[0];
if (node != null) Console.WriteLine(node.InnerText);
}
}
finally
{
Marshal.ReleaseComObject(session);
}
}
}
finally
{
Marshal.ReleaseComObject(options);
}
}
hope this helps, regards
I've got an article that describes an easy way to run Powershell through WinRM from .NET at http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/.
The code is in a single file if you want to just copy it and it's also a NuGet package that includes the reference to System.Management.Automation.
It auto manages trusted hosts, can run script blocks, and also send files (which isn't really supported but I created a work around). The returns are always the raw objects from Powershell.
// this is the entrypoint to interact with the system (interfaced for testing).
var machineManager = new MachineManager(
"10.0.0.1",
"Administrator",
MachineManager.ConvertStringToSecureString("xxx"),
true);
// will perform a user initiated reboot.
machineManager.Reboot();
// can run random script blocks WITH parameters.
var fileObjects = machineManager.RunScript(
"{ param($path) ls $path }",
new[] { #"C:\PathToList" });
// can transfer files to the remote server (over WinRM's protocol!).
var localFilePath = #"D:\Temp\BigFileLocal.nupkg";
var fileBytes = File.ReadAllBytes(localFilePath);
var remoteFilePath = #"D:\Temp\BigFileRemote.nupkg";
machineManager.SendFile(remoteFilePath, fileBytes);
Hope this helps, I've been using this for a while with my automated deployments. Please leave comments if you find issues.
I would like to note that this shows an interop error by default in Visual Studio 2010.
c.f. http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead.aspx
There appear to be two ways to solve this. This first is documented in the article listed above and appears to be the correct way to handle the problem. The pertinent changes for this example is:
WSMan wsManObject = new WSMan();
This is in lieu of IWSMan wsman = new WSManClass(); which will throw the error.
The second resolution is to go to the VS2010—>Solution Explorer—>Solution—>Project—>References and select WSManAutomation. Right click or hit Alt-Enter to access the properties. Change the value of the "Embed Interop Types" property of the wsmauto reference.

Categories