Determine Documentum host name when using Documentum.Interop.DFC C# assembly - com

I'm working on some rather old C# code that uses Documentum DFC (Documentum.Interop.DFC.dll 6.5.0.18). The Documentum server settings are stored within the dfc.properties file stored on my local machine, for example:
dfc.docbroker.host[0]=xyzserver.xyzdomain.net
dfc.docbroker.port[0]=5432
I would like to be able to determine, and write to a log file, the Documentum "docbroker" host and port number whenever the Documentum COM objects are instantiated. Here's what I have so far:
DfClientX xClient = new DfClientXClass(); // <=== This xClient should have the host in there somewhere... right?
IDfLoginInfo login = xClient.getLoginInfo();
login.setUser( localUserName );
login.setPassword( localUserPassword );
xClient is an interface of type DfClientX, it is instantiated as a COM object.
Looping through all of the properties of the object suggested by this post looks promising.
I've searched on the Documentum boards with no luck so far. I realize this question will be difficult to answer without having access to the Documentum software, but it seems like it should be a rather simple task... perhaps someone with more general COM knowledge can help out?
Thanks in advance!

So after checking out the object in the Visual Studio watch window (not within the "tooltip" watch), I was able to use Intellisense to examine the properties available to the COM object and its properties. Here is how I am now able to determine the host name:
DfClientX xClient = new DfClientXClass();
IDfClient client = xClient.getLocalClient();
const string HOST_ATTRIBUTE = "dfc.docbroker.host";
var hostSetting = xClient.getLocalClient().getClientConfig().getString( HOST_ATTRIBUTE );
Logging.WriteLog( TraceEventType.Verbose, "*** {0} = {1}", HOST_ATTRIBUTE, hostSetting.ToString() );
Maybe this will help somebody else in the future.

Related

VB.NET-Trying to populate vss files in tree view

I am trying to replicate the tree style view in Source Safe into my application in vb.net... I have already added the COM objects and connected to Source Safe database successfully... What i need is the method to populate the tree view with Source Safe files.... The logic to populate it and other necessary info... Can anyone HELP me???
I have inserted the tree view in my form
I have added the COM object for source safe
I have connected to source safe 'srcsafe.ini' file for database connection
I know i can use recursive program to fetch all the files in source safe
The only problem is i don't know about source safe functions. I have tried the MSDN website and read about all the properties of source safe. But how i use them, need some example.
And about flags in source safe, what i need to do to those flags when i perform the source safe functions from my application .
And how can i make the user restrictions like in source safe to my application
]
Here is documentation on VSS Automation. I had another link but it appears to be broken now.
http://msdn.microsoft.com/en-us/library/bb509341(v=vs.80).aspx
To work with VSS you would first create an instance of the VSSDatabaseClass class and call its Open method:
Dim vssDatabase As String = "\\server\somepath\srcsafe.ini"
Dim ssdb As new VSSDatabaseClass()
ssdb.Open(vssDatabase, userName, password)
The two methods that you will use most often are get_VSSItem() and get_Items(). These will return a singile VSSItem (which is a file or project) or a collection of items. So to get the root project of the database, you would use code such as this:
Dim root As IVSSItem = ssdb.getVSSItem("$/", False)
The Type property of a VSSItem indicates if the item is a project or file. If it is a project, you can get its child items using get_Items:
If root.Type = 0 Then 'Type = 0 means it's a project
Dim items As IVSSItems = root.get_Items(False)
For Each item As IVSSItem In items
If item.Type = 0 Then
'item is a project
Else
'item is a file
End If
Next
End If
I hope this gets you started.

How can I use LinqPad's generated context in Visual Studio

This is a follow-on from this question really:
Moving From LINQpad to a Proper Visual Studio Project?
..but I'm not able to get it to work properly.
An answer to that question suggestions dumping the context assembly out as a dll but although I have done that, when I import it as a reference, it's not exactly clear to me how I would create an instance of that context, point it at a database and actually run a query against it, something like the following:
var db = new ContextFromThatDLL(myconnectionstring);
var query = from a in db.MYTABLE where a.ID == 1 select a;
Extra information:
I am using the IQ driver in LinqPad to connect to Oracle.
I do have a license for DevArt already (which the IQ driver uses) but am aware that the IQ driver generates its own SQL from LINQ - and I prefer it. Plus, I develop queries in LinqPad which works great for my workflow but find that DevArt doesn't always generate SQL as good as IQ.
First, extract the typed data context in LINQPad as follows:
string dcPath = GetType().BaseType.Assembly.Location;
string targetFolder = #"c:\temp";
File.Copy (dcPath, Path.Combine (targetFolder, Path.GetFileName (dcPath)));
Then in Visual Studio, reference the typed data context DLL, along with the following DLLs from the driver folder:
IQDriver.dll
IQToolkit.dll
IQToolkit.Data.dll
IQToolkit.Data.(provider).dll
plus the DevArt driver.
Then, you can instantiate the typed data context as follows (this illustrates how to do it for SQLite):
var dc = new LINQPad.User.TypedDataContext (IQToolkit.Data.DbEntityProvider.From
("IQToolkit.Data.Sqlite", #"Data Source=D:\SQLite.NET\nutshell.db",
"LINQPad.User.TypedDataContext"));
var customerCount = dc.Customers.Count();
This should get you started. Bear in mind the caveats, as stated in the answer to which you linked!

Applying SSIS Package Configuration to multiple packages

I have about 85 SSIS packages that are using the same connection manager.
I understand that each package has its own connection manager.
I am trying to decide what would be the best configurations approach to simply set the connectionstring of the connection manager based on the server the packages are residing on.
I have visited all kinds of suggestions online, but cannot find anywhere the practice where I can simply copy the configuration from one package to the rest of the packages.
There are obviously many approaches such as XML file, SQL Server, Environment Variable, etc.
All the articles out there are pointing to use an Indirect method by using XML or SQL approach. Why would using an environment variable for just holding a connection string is such a bad approach?
Any suggestions are highly appreciated.
Thanks!
Why would using an environment variable for just holding a connection string is such a bad approach?
I find the environment variable or registry key configuration approach to be severely limited by the fact that it can only configure one item at a time. For a connection string, you'd need to define an environment variable for each catalog on a given server. Maybe it's only 2 or 3 and that's manageable. We had a good 30+ per database instance and we had multi-instanced machines so you can see how quickly this problem explodes into a maintenance nightmare. Contrast that with a table or xml based approach which can hold multiple configuration items for a given configuration key.
...best configurations approach to simply set the connectionstring of the connection manager based on the server the packages are residing on.
If you go this route, I'd propose creating a variable, ConnectionString and using it to configure the property. It's an extra step but again I find it's easier to debug a complex expression on a variable versus a complex expression on a property. With a variable, you can always pop a breakpoint on the package and look at the locals window to see the current value.
After creating a variable named ConnectionString, I right click on it, select Properties and set EvaluateAsExpression equal to True and the Expression property to something like "Data Source="+ #[System::MachineName] +"\\DEV2012;Initial Catalog=FOO;Provider=SQLNCLI11.1;Integrated Security=SSPI;"
When that is evaluated, it'd fill in the current machine's name (DEVSQLA) and I'd have a valid OLE DB connection string that connects to a named instance DEV2012.
Data Source=DEVSQLA\DEV2012;Initial Catalog=FOO;Provider=SQLNCLI11.1;Integrated Security=SSPI;
If you have more complex configuration needs than just the one variable, then I could see you using this to configure a connection manager to a sql table that holds the full repository of all the configuration keys and values.
...cannot find anywhere the practice where I can simply copy the configuration from one package to the rest of the packages
I'd go about modifying all 80something packages through a programmatic route. We received a passel of packages from a third party and they had not followed our procedures for configuration and logging. The code wasn't terribly hard and if you describe exactly the types of changes you'd make to solve your need, I'd be happy to toss some code onto this answer. It could be as simple as the following. After calling the function, it will modify a package by adding a sql server configuration on the SSISDB ole connection manager to a table called dbo.sysdtsconfig for a filter named Default.2008.Sales.
string currentPackage = #"C:\Src\Package1.dtsx"
public static void CleanUpPackages(string currentPackage)
{
p = new Package();
p.app.LoadPackage(currentPackage, null);
Configuration c = null;
// Apply configuration Default.2008.Sales
// ConfigurationString => "SSISDB";"[dbo].[sysdtsconfig]";"Default.2008.Sales"
// Name => MyConfiguration
c = p.Configurations.Add();
c.Name = "SalesConfiguration";
c.ConfigurationType = DTSConfigurationType.SqlServer;
c.ConfigurationString = #"""SSISDB"";""[dbo].[sysdtsconfig]"";""Default.2008.Sales""";
app.SaveToXml(sourcePackage, p, null);
}
Adding a variable in to the packages would not take much more code. Inside the cleanup proc, add code like this to add a new variable into your package that has an expression like the above.
string variableName = string.Empty;
bool readOnly = false;
string nameSpace = "User";
string variableValue = string.Empty;
string literalExpression = string.Empty;
variableName = "ConnectionString";
literalExpression = #"""Data Source=""+ #[System::MachineName] +""\\DEV2012;Initial Catalog=FOO;Provider=SQLNCLI11.1;Integrated Security=SSPI;""";
p.Variables.Add(variableName, readOnly, nameSpace, variableValue);
p.Variables[variableName].EvaluateAsExpression = true;
p.Variables[variableName].Expression = literalExpression;
Let me know if I missed anything or you'd like clarification on any points.

Using System.Reflection and resources in Phalanger

I need to embed some resource in a pure compiled dll written in php using phalanger.
These are txt files tha I set in visual studio as "Embedded Resource".
My problem is that I cannot use the Assembly class to get the resource using GetManifestResourceStream.
I tried code like this:
use System\Reflection\Assembly
$asm = Assembly::GetExecutingAssembly(); //this gives me mscorlib instead of my dll
$str = $asm->GetManifestResourceStream("name");
My question is: how do I get access to embedded resources in phalanger?
Many thanks
I'm not sure, why Assembly::GetExecutingAssembly() returns an incorrect value. Anyway to workaround the $asm value, use following code:
$MyType = CLRTypeOf MyProgram;
$asm = $MyType->Assembly;
Then you can access embedded resources as you posted
$asm->GetManifestResourceStream("TextFile1.txt");
or you can include standard resource file (.resx) into your project, and use \System\Resources\ResourceManager
$this->manager = new \System\Resources\ResourceManager("",$asm);
$this->manager->GetObject("String1",null);
Just note, currently there can be just one .resx within Phalanger project
This question is old, but the part of the Phalanger code (Php.Core.Emit.AddResourceFile() method) responsible for this hasn't changed since this was asked. I faced the same problem and solved it in (almost) non-hacky way. You have to provide alternative name (/res:/path/to/filename,alternative-name) for this to work though.
$asm = clr_typeof('self')->Assembly;
$resourceStream = $asm->GetManifestResourceStream("filename");
$reader = new \System\Resources\ResourceReader($resourceStream);
$type = $data = null;
$reader->GetResourceData("alternative-name", $type, $data);
// and still there are 4 excess bytes
// representing the length of the resource
$data = \substr($data, 4);
$stream = new IO\MemoryStream($data);
// after this $stream is usable as you would expect
Straightforward GetManifestResourceStream() (as suggested by Jakub) does not work because Phalanger does not use System.Reflection.Emit.ModuleBuilder.DefineManifestResource() (like I think it should when supplied with unrecognized file format). It uses ModuleBuilder.DefineResource() which returns ResourceWriter instead, that only really suited for .resources files. And this is what dictates the requirement to use ResourceReader when you need to read your resource.
Note: This answer applies to Phalanger master branch at the time of writing and prior versions since circa 2011. Noted because it looks like a bug (especially the need to use both original and alternative names).

Unable to determine the identity of domain using System.IO.Packaging

I am getting "Unable to determine the identity of domain" when using System.IO.Packaging through COM Interop, there are a few articles describing why this is happening and the solution is to run the offending function in its own AppDomain.
So I took the sample code, which looks like the below but I still get the error, I am wondering what i am doing wrong and also, with VS 2010 it says AddAssembly and AddHost are obsolete - I wonder if that means they are no longer implemented, but if thats the case I dont really understand how to use the new methods (AddAssemblyEvidence and AddHostEvidence)??
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
evidence.AddAssembly(Assembly.GetExecutingAssembly().FullName);
evidence.AddHost(new Zone(SecurityZone.MyComputer));
AppDomain domain = AppDomain.CreateDomain("BlobPackage", evidence, setup);
BlobPackage blob_interal = (BlobPackage)domain.CreateInstanceAndUnwrap(typeof(BlobPackage).Assembly.FullName, typeof(BlobPackage).FullName);
blob_interal.pack(FilePath, RootPath, m_source_files); <-- STILL FAILS
AppDomain.Unload(domain);
I solved this one myself, I forgot to inherit my class from MarshalByRefObject.
Its a bit stupid, it allows you to create an instance and call it except its still running in the default domain, you would think it would throw an exception or something, anyway by marking the class as [Serializable()] and deriving from MarshalByRefObject fixes it.