PowerShell: Check whether a Windows command or executable is available

In one of my recent PowerShell scripts I needed to find out if certain commands (in my case „svn“, „git“, „ant“ and „mvn“) were available or not. I wrote this small function that tries to call the given command and returns whether it is callable.

  1. function commandAvailable($cmd, $options)
  2. {
  3.   $error.clear();
  4.   $ErrorActionPreference = "silentlycontinue";  
  5.   & $cmd $options | out-null;
  6.   if ($error[0])
  7.   {
  8.     write-host ("Command " + $cmd + " " + $options + " is not available") -foregroundcolor "red";
  9.     return $false;
  10.   }
  11.   return $true;
  12. }
  13.  
  14. write-host (commandAvailable "svn" "–version");

VBoxManage: error: VT-x features locked or unavailable in MSR. (VERR_VMX_MSR_LOCKED_OR_DISABLED)

Today I wanted to add a new 64bit virtual machine to my VirtualBox installation but when I tried to power it on I got the following error message:

root@debian /home/vms/Webserver # VBoxManage startvm Webserver --type headless
Waiting for VM "Webserver" to power on...
VBoxManage: error: VT-x features locked or unavailable in MSR. (VERR_VMX_MSR_LOCKED_OR_DISABLED)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component Console, interface IConsole, callee

The VirtualBox forum lists two prerequisites for using hardware virtualization in your VMs:

  1. a 64bit processor, which apparently I had:
    root@debian /home/vms/Webserver # lscpu
    Architecture:          x86_64
    CPU op-mode(s):        32-bit, 64-bit
  2. hardware virtualization has to be enabled in the host’s BIOS, which as it turned out I didn’t have:
    root@debian /home/vms/Webserver # modprobe msr
    root@debian /home/vms/Webserver # rdmsr 0x3a
    1

    (here’s a German description of the command above: Virtualisierungsfunktion Intel VT aktivieren)

After enabling the hardware virtualization feature (VT-X) in the host’s BIOS and restarting it, the VM could be powered on.

Oracle error ORA-01000 (maximum open cursors exceeded) occurs when querying via ODBC with C#

A colleague of mine had this interesting problem today: OdbcDataAdapter ORA-01000. When querying an Oracle database via ODBC from C# using the following code, an Oracle error ORA-01000: maximum open cursors exceeded occured after a certain number of iterations (300 in our case):

  1. static void Main(string[] args)
  2. {
  3.     var connectionString = "DSN=MYDB;UID=user;PWD=pass";
  4.     var connection = new OdbcConnection(connectionString);
  5.     var sql = "Select 1 From DUAL";
  6.     connection.Open();
  7.  
  8.     for (int i = 1; i < 500; i++)
  9.     {
  10.         using (var dataAdapter = new OdbcDataAdapter(sql, connection))
  11.         {
  12.             var dataTable = new DataTable();
  13.             dataAdapter.Fill(dataTable); // -> error ORA-01000 in iteration 300
  14.             Console.WriteLine("Iteration {0,8:d} Count = {1,4}", i, dataTable.Rows.Count);
  15.         }
  16.     }
  17.  
  18.     connection.Close();
  19. }

As it turns out, the OdbcCommand object, that the OdbcDataAdapter uses internally (see field OdbcDataAdapter.SelectCommand), has to be disposed explicitly to get rid of the error. A simple dataAdapter.SelectCommand.Dispose() at the end of the using block would do the job, but there is an even cleaner way:

  1. for (int i = 1; i < 500; i++)
  2. {
  3.     using (var command = new OdbcCommand(sql, connection)) // -> makes sure command gets disposed
  4.     using (var dataAdapter = new OdbcDataAdapter(command))
  5.     {
  6.         …
  7.     }
  8. }

Connecting to an Oracle database via ODBC using only the InstantClient

Until today, I thought to be able to connect to an Oracle database from your Windows machine, you need to install the complete Oracle client including the Enterprise Manager etc. (>1GB). However, today I finally found a way to use Oracle via ODBC using only the InstantClient (ca. 50MB) on the Oracle website:

  1. First of all, download the InstantClient and the corresponding ODBC drivers for your platform from Oracle’s download site.
  2. Extract the archives into a directory of your choice, e.g. D:\Dev\Oracle\instantclient_11_2 (from now on referred to as %INSTALLDIR%).
    Connect to Oracle via ODBC using the InstantClient (directory structure)
  3. Run odbc_install.exe in %INSTALLDIR%.
    Connect to Oracle via ODBC using the InstantClient (installing the ODBC driver)
  4. Create the directory %INSTALLDIR%\network\admin and place your tnsnames.ora file in that directory.
    Connect to Oracle via ODBC using the InstantClient (adding tnsnames.ora)
  5. Set the environment variable ORACLE_HOME to %INSTALLDIR%.
    Connect to Oracle via ODBC using the InstantClient (setting ORACLE_HOME)
  6. Configure a new ODBC data source using InstantClient.
    Connect to Oracle via ODBC using the InstantClient (creating an ODBC data source)

That’s it! Now you’ll be able to connect to your Oracle database via ODBC.

PowerShell: How to read contents from text files without converting the lines into an array

Apparently, PowerShell’s get-content cmdlet automatically converts the contents of text files into an array of strings, splitting the contents at the line breaks (see Using the Get-Content Cmdlet). In many cases this is convenient:

Contents of file test.txt:

1
2
3
gc text.txt | % { write-host „line: “ $_ }
line: 1
line: 2
line: 3

However, if you need the file’s contents as an unchanged string (e.g. to keep line breaks the way they are when working with Unix/Linux line endings) this is not what you want. In this case, you can use the .NET method File.ReadAllText() (see File.ReadAllText Method:

[System.IO.File]::ReadAllText(„text.txt“)
1
2
3

Stellenangebot: Softwareentwickler/in und Systemadministrator/in in Vechta gesucht

Mein Arbeitgeber, die ALTE OLDENBURGER AG, sucht zur Zeit mal wieder neue Kollegen/innen im EDV-Bereich:

Stellenangebote bei der ALTE OLDENBURGER AG.

Softwareentwickler/in

Ihre Aufgaben

  • Neu- und Weiterentwicklung versicherungstechnischer Anwendungen
  • Plattformübergreifende Integration prozessunterstützender Anwendungssysteme
  • Wartung der betreuten Anwendungen und Beratung der Fachbereiche

Ihr Profil

  • Abgeschlossene Ausbildung zum Fachinformatiker Anwendungsentwicklung oder ein abgeschlossenes (FH-)Studium im Bereich (Wirtschafts-)Informatik oder Software-Engineering.
  • Idealerweise 2 Jahre Berufserfahrung in der Softwareentwicklung in mind. einer der Programmiersprachen Java, C# oder Natural.
  • Breites Interessenspektrum und die Bereitschaft zur selbstständigen Einarbeitung in verschiedene technologische Bereiche.

Systemadministrator/in

Ihre Aufgaben

  • Administration unserer Windows- und Linux-Netzwerkinfrastruktur
  • Betreuung unseres Dokumentenmanagementsystems
  • Administration unserer Citrix- und VMWare-Infrastruktur
  • Unterstützung bei Support und Dokumentation sowie Koordination verschiedener Dienstleister

Ihr Profil

  • Abgeschlossene Ausbildung zum Fachinformatiker Systemintegration oder ein abgeschlossenes (FH-)Studium der (Wirtschafts-)Informatik.
  • Idealerweise 2 Jahre Berufserfahrung in der (Netzwerk-)Administration von Linux- und Windows-Servern.
  • Optional Berufserfahrung in der Administration von Oracle-Datenbanken.
  • Breites Interessenspektrum und die Bereitschaft zur selbstständigen Einarbeitung in verschiedene technologische Bereiche.

Copying files larger than 2GB to a mounted Samba share on Linux

Today we had a problem copying a large file (>4GB) to a Samba share using Linux. The share was mounted via smbmount and worked perfectly for all other files. However, the large file was copied to the share only up to a size of 2GB and then the copying aborted.

The solution was to mount the share with the option lfs (apparently this is short for „large file system“), e.g. like this in /etc/fstab:

//server/share$ /local/path smbfs lfs,username=user,password=secret 0 0

FLOW3: Convert a date string from an input field of a view into a DateTime object

As I’ve mentioned earlier, the FLOW3 documentation is a bit weak at the moment. The initial example walks you through a very simple view where only strings (like „title“, „author“) are entered via the view’s form. But how do you enter a date and have it converted to a „real“ \DateTime upon initializing the object that should contain it?

I found the solution (again, mainly by chance) here: How to use the DateTimeConverter in FLOW3. Apparently, you have to convert the user’s input to the needed objects in a method in the corresponding controller, that is (magically?) called before the method that expects the main object you want to create (that contains the date).

Here’s an example: If you have a Report object that has a dueDate attribute of type \DateTime, you have to convert the user input (a string) to a \DateTime object in the method initializeCreateAction() of class ReportController.

FLOW3 offers quite a few type converters, among which you can also find a DateTimeConverter. You can use it like this in initializeCreateAction():

  1. public function createAction(Report $report) { }
  2.  
  3. public function initializeCreateAction() {
  4.   $this->arguments[‚report‘]
  5.     ->getPropertyMappingConfiguration()
  6.     ->forProperty(‚dueDate‘)
  7.     ->setTypeConverterOption(
  8.       ‚TYPO3\FLOW3\Property\TypeConverter\DateTimeConverter‘,
  9.       \TYPO3\FLOW3\Property\TypeConverter\DateTimeConverter::CONFIGURATION_DATE_FORMAT,
  10.       ‚Y-m-d‘);
  11. }

FLOW3 now converts the input string (format ‚Y-m-d‘) into a „real“ \DateTime object before passing it on to the newly created Report object, that gets passed to createAction().

L4N (Log4Nat) – a logging framework for Natural (by Software AG)

Along with NatUnit (a unit testing framework) we released L4N (or Log4Nat, or Log4Natural ;-)) on SourceForge today: L4N on SourceForge.

L4N offers basic logging functionality for Natural (by Software AG), including:

  • user- and module-specific logging
  • different log levels (e.g. debug, info, error)
  • combinable logging facilities (e.g. work file, INPUT, WRITE, database)

Using the framework is easy, as the following code shows:

  1. LOCAL USING L4NCONST /* some constants like log levels etc.
  2. LOCAL USING L4NPARAM /* the parameters (e.g. log text) for calling the actual logging
  3. * (optional) basic configuration of logging for the current module
  4. L4N-DEBUGUSER := ‚macke‘
  5. L4N-LOGTYPES := C-LOGTYPE-FILE + C-LOGTYPE-WRITE
  6. L4N-LINENR := *LINE; L4N-DEBUGLEVEL := C-LOGLEVEL-DEBUG
  7. INCLUDE L4NENTER
  8. * the actual logging
  9. COMPRESS ‚Current value:‘ #VALUE INTO L4N-LOGTEXT
  10. L4N-LINENR := *LINE; L4N-LOGLEVEL := C-LOGLEVEL-INFO
  11. INCLUDE L4NLOGIT

L4N is licensed under LGPL v3, so feel free to use it in your (commercial) applications or even help us further develop the framework.

NatUnit (former NUNIT) on SourceForge

We published NatUnit (former NUNIT) on SourceForge today: NatUnit on SourceForge.

Due to naming conflicts with the „real“ NUnit, we decided to publish it as NatUnit. However, the internal name is still NUNIT, as Natural module names are restricted to a length of 8 characters which left us with only one character to distinguish between modules, if we used NATUNIT 😉

NatUnit is easy to use, as the following code (a simple test case) shows. The whole framework is written in Natural itself, so you don’t have to use external tools like NaturalONE.

  1. DEFINE DATA
  2. PARAMETER USING NUTESTP
  3. LOCAL USING NUCONST
  4. LOCAL USING NUASSP
  5. END-DEFINE
  6. *
  7. NUTESTP.FIXTURE := ‚Example TestCase 1‘
  8. *
  9. INCLUDE NUTCTEMP
  10. INCLUDE NUTCSTUB
  11. *
  12. DEFINE SUBROUTINE TEST
  13. *
  14. ********************************************************************************
  15. IF NUTESTP.TEST EQ ‚compare two equal numbers should pass‘
  16. ********************************************************************************
  17. ASSERT-LINE := *LINE; PERFORM ASSERT-NUM-EQUALS NUASSP 2 2
  18. END-IF
  19. *
  20. END-SUBROUTINE
  21. *
  22. END

NatUnit is licensed under LGPL v3, so feel free to use it in your (commercial) applications or even help us further develop the framework.