Programming tools |
I commonly find that a body of code gets littered with cut-and-paste after awhile. So I developed a tool that I thought would help in identifying the sections that need to be refactored since duplicated code can be reduced. Refactor finds duplicated segments of text that are at least four lines long and where the duplication does not start with an empty line, a solo {, or a solo }. (My roots are in C/C++, don't you know.)
Refactor is a .NET binary and requires the 1.0 framework. It runs on the command line and sends its findings to stdout. The only command line arguments are file names or the name of a file that contains a list of files to operate on.
Sample usage:
refactor *.cs
Or:
dir /S /B *.cpp > list refactor @list > result
Referring links:
If you have to use VB5 (or earlier) and you have to create objects remotely without using DCOMCNFG, then you might be interested in this ATL/C++ code to do precisely this.
Sample usage:
Option Explicit
Dim obj
Set obj = CreateObject ("ObjectCreator.Creator.1")
MsgBox "Got the creator object"
Dim RemoteObject
Set RemoteObject = obj.NewObject ("ARBSimulationEngine_54", "WINDOK")
MsgBox "Got the target object"
Set RemoteObject = Nothing
Set obj = Nothing
MsgBox "Done"
One of the major irritations of COM development is that you frequently have multiple copies of your servers around but they do not match the one you think you are using. CoWhereIs provides answers to the questions:
CoWhereIs is a command line program that takes CLSIDs, either as GUIDs or as ProgIDs, as arguments. This script:
CoWhereIs ArbReport.Engine CoWhereIs ArbAggregator.Aggregator CoWhereIs ArbStart.Factory CoWhereIs CurveBookServer CoWhereIs ARBReportOcx.ARBReport CoWhereIs ARBReportOcx.ReportEngineInterface CoWhereIs ArbEngine CoWhereIs ARBBlob.BlobObject
Produces this output:
LocalServer32 ArbReport.Engine is at D:\AskariRiskBook53a\bin\ARBReportEngine.EXE LocalServer32 ArbAggregator.Aggregator is at C:\TEMP\ARBAggregator.exe InprocServer32 ArbStart.Factory is at D:\AskariRiskBook53a\bin\ARBStart.dll LocalServer32 CurveBookServer is at D:\AskariRiskBook53aa\bin\CurveBookServer.EXE INFO: File D:\AskariRiskBook53aa\bin\CurveBookServer.EXE does not exist InprocServer32 ARBReportOcx.ARBReport is at D:\AskariRiskBook53aa\bin\ARBReport.OCX INFO: File D:\AskariRiskBook53aa\bin\ARBReport.OCX does not exist LocalServer32 ArbEngine is at D:\AskariRiskBook53a\bin\Simulation.EXE InprocServer32 ARBBlob.BlobObject is at C:\ASKARI~1\src\Blob\Debug\ARBBlob.dll INFO: File C:\ASKARI~1\src\Blob\Debug\ARBBlob.dll does not exist
Notice that it says that some of the components are not physically present, even though CoWhereIs indicates they are the components that COM will use. These will cause errors at runtime.
Disclaimer: tested in NT 4.0 up to SP4. No promises for NT 5.0.
People in the DCOM mailing list have asked me for the source code I offered for using ADO disconnected recordsets from the client. Well, here it is. There are several disclaimers that apply, including:
On the plus side, I don't know of any published code that shows how to do this at all (i.e. without any OLEDB data source), so there may still be some value to you.
If you make changes to the source code or otherwise make worthwhile discoveries, please let me know. I would be interested. I have heard that rs.CacheSize would help performance, but I have not tested this.
RetData.zip contains the server code.
VCText.zip contains the VC++ 6.0 client code.
Here are some related links on ADO that you may find useful:
Occasionally, it is really useful to be able to create an object and add reference counting semantics to it apart from its identity as an object. I find this particularly useful with COM when a parent object owns some functionality but still has to pass it on to its child objects. I don't like having children with references to their parents, so I give the parent and the child a reference to the object wrapped in a reference counting template.
Here is sample code to demonstrate its use:
#include "stdafx.h"
#include "RefTemplate.h"
class Foo
{
public:
Foo ()
{
printf ("Foo\n");
}
~Foo ()
{
printf ("~Foo\n");
}
char *Hello ()
{
printf ("Foo::Hello! (%08lx)\n", (long) this);
return "Hello";
}
};
class Bar
{
public:
RefTemplate<Foo> x;
long z;
public:
Bar ()
: z(42)
{
printf ("Bar\n");
}
void Init (Foo *ptr)
{
x = RefTemplate<Foo>(ptr);
}
~Bar ()
{
printf ("~Bar\n");
}
};
int main(int argc, char* argv[])
{
Bar bar_x, bar_y, bar_z;
printf ("\nMade x and z\n\n");
Foo *y = new Foo;
printf ("\nMade Foo\n\n");
bar_x.Init (y);
printf ("\nx.Init done\n\n");
bar_z = bar_x;
bar_y = bar_z;
bar_x = bar_y;
bar_z = bar_x;
bar_y = bar_z;
bar_x = bar_y;
printf ("\nassignments Done\n\n");
Foo *tmp = (Foo *) bar_x.x; //bar_x.x;
tmp->Hello ();
bar_z.x->Hello ();
Bar *b = &bar_z;
printf ("Bar::z = %ld\n", b->z);
printf ("Bar::Hello = %s\n", b->x->Hello());
printf ("\nx.x->Hello() done\n\n");
return 0;
}
© 2001-3 Hugh Brown. All rights reserved.