Inserting to an msi database from c# - c#

I am trying to insert a new property into the msi file. I am able to update the msi database file using the following code.Is there a way to add new values into a table. I am not able to find any.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WindowsInstaller;
namespace msiExample
{
[System.Runtime.InteropServices.ComImport(), System.Runtime.InteropServices.Guid("000C1090-0000-0000-C000-000000000046")]
class Installer { }
class msiMain
{
static void Main(string[] args)
{
WindowsInstaller.Installer ins = (WindowsInstaller.Installer)new Installer();
string strFileMsi = #"C:\APP.msi";
System.Console.WriteLine("STARTING SECOND QUERY");
Database db2 = ins.OpenDatabase(strFileMsi, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeDirect);
View vw2 = db2.OpenView(#"Select * FROM Property where Value='Unknown'");
vw2.Execute(null);
Record rcrd2 = vw2.Fetch();
while (rcrd2 != null)
{
System.Console.WriteLine(rcrd2.get_StringData(1));
rcrd2.set_StringData(1,"No data");
vw2.Modify(WindowsInstaller.MsiViewModify.msiViewModifyUpdate, rcrd2);
rcrd2 = vw2.Fetch();
}
db2.Commit();
vw2.Close();
System.Console.WriteLine("completed");
}
}
}

Windows Installer XML (WiX) Deployment Tools Foundation (DTF) libraries help a lot here. The easiest way I know to do it is:
using Microsoft.Deployment.WindowsInstaller.Linq;
using (QDatabase database = new QDatabase(#"C:\data\test.msi", DatabaseOpenMode.Direct))
{
var record = database.Properties.NewRecord();
record.Property = "MyProperty";
record.Value = "MyValue";
record.Insert();
}
If you still want to think SQL then:
using Microsoft.Deployment.WindowsInstaller;
using (Database database = new Database(#"C:\data\test.msi", DatabaseOpenMode.Direct))
{
database.Execute("INSERT INTO `Property` (`Property`, `Value`) VALUES('MyProperty', 'MyValue')");
}

the DTF answer from Christopher Painter is better but with the com objet, based on your code :
WindowsInstaller.View vw2 = db2.OpenView("INSERT INTO Property (Property, Value) VALUES ('property_name', 'property_value')");
vw2.Execute(null);
db2.Commit();
vw2.Closed();

Use ` for name of tables and columns
Use ' for strings values

Related

c# read/edit accdb macro

I am trying to access the macros inside of an Access database (accdb).
I tried using:
using Microsoft.Office.Interop.Access.Dao;
...
DBEngine dbe = new DBEngine();
Database ac = dbe.OpenDatabase(fileName);
I found a container["Scripts"] that had a document["Macro1"] which is my target. I am struggling to access the contents of the document. I also question if the Microsoft.Office.Interop.Access.Dao is the best reference for what I am trying to achieve.
What is the best way to view the content of the macros and modules?
You can skip the DAO part, it's not needed in this case. Macros are project specific, so in order to get them all, you would need to loop through your projects. In my example, i just have one project.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Access;
namespace Sandbox48
{
public class Program
{
public static void Main(string[] args)
{
Microsoft.Office.Interop.Access.Application oAccess = null;
string savePath = #"C:\macros\";
oAccess = new Microsoft.Office.Interop.Access.Application();
// Open a database in exclusive mode:
oAccess.OpenCurrentDatabase(
#"", //filepath
true //Exclusive
);
var allMacros = oAccess.CurrentProject.AllMacros;
foreach(var macro in allMacros)
{
var fullMacro = (AccessObject)macro;
Console.WriteLine(fullMacro.Name);
oAccess.SaveAsText(AcObjectType.acMacro, fullMacro.FullName, $"{savePath}{ fullMacro.Name}.txt");
}
Console.Read();
}
}
}

Where do I put the dlls for edge.js to access

I have been using edge.js to call a C# function from within my Node.js app, however when I go to execute the C# code I get for example:
Metadata file 'System.Collections.Generic.dll' could not be found
Metadata file 'System.Text.dll' could not be found
...
My code is this below, basically wanting to run a SSIS package using a stored procedure which I am calling from C#. Basically all my referenced dll's can't be found? Where should I put the dlls for edge to find them?
var executeSQL = edge.func(function() {
/*
#r "System.Data.dll"
#r "System.Collections.Generic.dll"
#r "System.Linq.dll"
#r "System.Text.dll"
using System.Linq;
using System.Text;
using System.Data;
using System.Collections.Generic;
using System.Threading.Tasks;
public class StartUp
{
public async Task<object> Invoke(object input)
{
string result = string.Empty;
string packagePath = #"\SSISDB\test\package.dtsx";
string spName = "storedProcName";
using (var conn = new System.Data.SqlClient.SqlConnection("connectionString"))
using (var command = new System.Data.SqlClient.SqlCommand(spName, conn)
{
CommandType = System.Data.CommandType.StoredProcedure
})
{
conn.Open();
command.Parameters.AddWithValue("#PackagePath", packagePath);
command.ExecuteNonQuery();
Console.WriteLine("Finished");
};
return null;
}
}
*/
});
I know I can do this without C# and just use a module within node like mssql to execute the stored procedure but this was just an example test to get used to using edge.js
The comment from stuartd was correct in the sense to put the dlls under the same directory as the script (which I had tried) but I was still having the same issue. I solved my problem by having my C# code as a separate file and then referenced that file as below as part of the executeSSIS function. payload is just the object that gets passed from my node.js script to my C# script. Doing it this way solved my issue.
var payload = {
filePath: 'C:/temp/xlsx/' + req.file.filename,
path: req.packageName,
server: req.server
};
var executeSSIS = edge.func({
source: __dirname + '/cs/Program.cs',
references: [
__dirname + '/cs/System.Data.dll'
]
});
executeSSIS(payload);

C# cannot connect to vmware

I have a project where i will have to build dual stacked virtual machines. I usually work with powershell but it does not appear to be able to do that. I may have to use C#. I am kinda rusty on this but for some reason this code give me an error "Cannot create an instance of the abstract class or interface 'VMware.Vim.VimClient'".
using System.Text;
using VMware.Vim;
namespace Vimfunctions
{
public class VimFunctions
{
protected VimClient ConnectServer(string viServer, string viUser, string viPassword)
{
**VimClient vClient = new VimClient();**
ServiceContent vimServiceContent = new ServiceContent();
UserSession vimSession = new UserSession();
vClient.Connect("https://" + viServer.Trim() + "/sdk");
vimSession = vClient.Login(viUser, viPassword);
vimServiceContent = vClient.ServiceContent;
return vClient;
}
I added the reference to the project. I must have forgot to do something.
As per https://communities.vmware.com/thread/478700:
"either stick with the PowerCLI 5.5 release as mentioned or to modify your code to use the VimClientImpl class instead of VimClient (which is now an interface)."
A complete simple example I used:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VMware.Vim;
namespace vSphereCli
{
class Program
{
static void Main(string[] args)
{
VMware.Vim.VimClientImpl c = new VimClientImpl();
ServiceContent sc = c.Connect("https://HOSTNAME/sdk");
UserSession us = c.Login("admin#vsphere.local", "password");
IList<VMware.Vim.EntityViewBase> vms = c.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, null, null);
foreach (VMware.Vim.EntityViewBase tmp in vms)
{
VMware.Vim.VirtualMachine vm = (VMware.Vim.VirtualMachine)tmp;
Console.WriteLine((bool)(vm.Guest.GuestState.Equals("running") ? true : false));
Console.WriteLine(vm.Guest.HostName != null ? (string)vm.Guest.HostName : "");
Console.WriteLine("");
}
Console.ReadLine();
}
}
}
Add a reference to "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll". Update the hostname, password; and volia!

is a namespace but is used like a 'type'

UPDATE
I've created the solution again.
File > New > Project > VisualC# > Console Application
Name : teststudent
Solution name : teststudent
Then from solution exploer I clicked on teststudent
Add > New Item > ADO.Net Entity Data Model > Generate from database
New connection :
save entity connection settings in App.Config as :
teststudententities
Which version of Entity Framework do you want to use?
6.0
Then I checked all tables.
Model Namespace:
teststudentModel
UPDATE ENDS
I'm trying to create a query to show all the records in a database table named students in Visual Studio 2013.
studentdb is the name of my database. I have established a connection to my SQL Server database. I can see the tables from the model in solution explorer. When I execute I get one build error :
'studentdb' is a 'namespace' but is used like a 'type'
the program.cs file :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace studentdb
{
class Program
{
static void Main(string[] args)
{
Query1();
}
private static void Query1()
{
using (var context = new studentdb())
{
var students = from studentdetails in context.students select studentdetails;
Console.WriteLine(" Query All students");
foreach (var student in students)
{
Console.WriteLine("{0} {1}", student.studentid, student.surname);
}
Console.Write("Press enter to exit"); Console.ReadLine();
}
}
}
}
Just rename namespace to something else at line 7
namespace anotherNamespace
{
You namespace and one of the class name is same
namespace studentdb
using (var context = new studentdb())
I think you meant var context = new studententities() or something similar not studentdb()
studentdb is the name of same namespace. So you can not use that like studentdb(). You can create object for only classes but not namespaces.

Entity Framework doesnt access via DLL to a Database

The full Code can be found here: http://home.htw-berlin.de/~s0531210/eb/DataBaseTest.zip
It is a simple Project with testing Entity Framework.
I have a DLL that allows access to a SQL Server Compact database. This access happens by Enttiy Framework 5.0.
A second project is a console application that accesses this DLL. When calling a class from the DLL to store sample data into the database, the exception is "Error underlying provider Open."
This exception occurs when calling: db.SaveChanges ();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DatabaseLibrary
{
public class SLD
{
public SLD()
{
}
public void enterData()
{
using (var db = new SLDDatabaseModelEntitiesContext())
{
for (int i = 0; i < 10; i++)
{
SLDEntity entrysfoo = new SLDEntity();
entrysfoo.Flip = i;
entrysfoo.Slidename = "bla" + i;
db.SLDEntity.Add(entrysfoo);
}
db.SaveChanges(); //DAtanbank speichern
}
}
public SLDEntity getFromDataBase(string wsiname)
{
using (var db = new SLDDatabaseModelEntitiesContext())
{
foreach (var item in db.SLDEntity)
{
if (item.Slidename.Equals(wsiname))
{
return item;
}
}
}
return new SLDEntity();
}
}
}
i hope you guys can help me. I have no clue where the problem is. I searched the internet and i found something about persmission iusses, but the connectionstring is reqiredpermissin=false.
thanks the tip with the connection string worked. The Database was not there where the App.config file from the consoleapp pointed at. but I do not understand why the connection string in the dll, which one also has a App.config File is ignored. If I want, that the connection string is available only in the DLL, Do I have to set the connection string in the DLL manually via a command?

Categories