Best windows questions in January 2011

How to get the word under the cursor in Windows?

23 votes

I want to create a application which gets the word under the cursor (not only for text fields), but I can't find how to do that. Using OCR is pretty hard. The only thing I've seen working is the Deskperience components. They support a 'native' way, but I they cost a lot. Now I'm trying to figure out what is this 'native' way (maybe somehow of hooking). Any help will be appreciated.

EDIT: I found a way, but it gets only the whole text of the control. Any idea how to get only the word under the cursor from the whole text?

On recent versions of Windows, the recommended way to gather information from one application to another (if you don't own the targeted application of course) is to use the UI Automation technology. Wikipedia is pretty good for more information on this: Microsoft UI Automation

Basically, UI automation will use all necessary means to gather what can be gathered

Here is a small console application code that will spy the UI of other apps. Run it and move the mouse over to different applications. Each application has a different support for various "UI automation patterns". For example, there is the Value pattern and the Text pattern as demonstrated here.

static void Main(string[] args)
{
    do
    {
        System.Drawing.Point mouse = System.Windows.Forms.Cursor.Position; // use Windows forms mouse code instead of WPF
        AutomationElement element = AutomationElement.FromPoint(new System.Windows.Point(mouse.X, mouse.Y));
        if (element == null)
        {
            // no element under mouse
            return;
        }

        Console.WriteLine("Element at position " + mouse + " is '" + element.Current.Name + "'");

        object pattern;
        // the "Value" pattern is supported by many application (including IE & FF)
        if (element.TryGetCurrentPattern(ValuePattern.Pattern, out pattern))
        {
            ValuePattern valuePattern = (ValuePattern)pattern;
            Console.WriteLine(" Value=" + valuePattern.Current.Value);
        }

        // the "Text" pattern is supported by some applications (including Notepad)and returns the current selection for example
        if (element.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
        {
            TextPattern textPattern = (TextPattern)pattern;
            foreach(TextPatternRange range in textPattern.GetSelection())
            {
                Console.WriteLine(" SelectionRange=" + range.GetText(-1));
            }
        }
        Thread.Sleep(1000);
        Console.WriteLine(); Console.WriteLine();
    }
    while (true);
}

UI automation is actually supported by Internet Explorer and Firefox, but not by Chrome to my knowledge. See this link: When will Google Chrome be accessible?

Now, this is just the beginning of work for you :-), because:

  • Most of the time, all this has heavy security implication. Using this technology (or direct Windows technology such as WindowFromPoint) will require sufficient rights to do so (such as being an administrator). And I don't think DExperience has any way to overcome these limitations, unless they install a kernel driver on the computer.

  • Some applications will not expose anything to anyone, even with proper rights. For example, if I'm writing a banking application, I don't want you to spy on what my application will display :-). Other applications such as Outlook with DRM will not expose anything for the same reasons.

  • Only the UI automation Text pattern support can give more information (like the word) than just the whole text. Alas, this specific pattern is not supported by IE nor FF even if they support UI automation globally.

So, if all this does not work for you, you will have to dive deeper and use OCR or Shape recognition techniques. Even with this, there will be some cases where you won't be able to do it at all (because of security rights).

C# Logging. What should I use?

15 votes

I'm looking at switching to a new unified logging solution for use in our new line of products and I wanted to see what some of the people on Stack Overflow thought. We will need logging for a variety of applicatons: ASP .net, windows services, web services, wpf apps etc. We are a windows shop only.

Some of our requirements for a logging solution include:

1) Log file management

- Ability to split files up over a certain size
- Ability to auto archive/delete after certain period of time

2) Ability to send emails on certain types of messages logged (errors for example)

3) Ability to write messages to the windows event log

- We need to be able to specify where it's being written in the event log. 
  It would also be nice if it would automatically create the event log source if it does exist.

I've started looking at nLog, windows trace and log4net. I'm not limited to these 3 only it's just a few that came up a lot when searching.

log4net is always a good choice.

http://logging.apache.org/log4net/

Automatically taking screenshots of program window

14 votes

I'm looking for a software that combines macro recording with screenshot taking capabilities.

We have a software manual with a number of screenshots. When new version of software is released we need to update most of screenshots and we have to do it manually. Now we started translating manual to several languages and number of screenshots to take have increased ten fold. We'd like to automate this process.

There will be a recorded macro or something that clicks button within our software and takes screenshots of the program window. Better yet, we can specify the name of each screenshot individually though it's less important.

Does such a thing exist?

I use AutoIt plus captdll.dll for all my Windows GUI automation tasks.

Example:

Run("Notepad.exe", @WindowsDir, @SW_MAXIMIZE)   ; Open NOTEPAD
Sleep(1000)
Send("Just a Test")   ; Send some text to notepad

; Save the screen to test.jpg  
$anPos = WinGetClientSize("")
$nLeft = 0
$nTop = 0
$nRight = $anPos[0]
$nBottom = $anPos[1]

$sFileName = "test.jpg"
DllCall("captdll.dll", "int:cdecl", "CaptureScreen", "str", $sFileName, "int", 85)

This way you can automate the entire screenshot capturing process:

  • start your application with Run
  • select each of your menu options with Send
  • complete each screen's data also with Send
  • capture with DllCall("captdll.dll" ....)

You can also add conditional logic, loop, etc.

Which scripting language is better for embedding in multi-threaded C/C++ application

12 votes

Considering the following requirementes:

  • Must be supported on Windows. Preferably works also on other platforms.
  • Must support multi threading. By that I mean that the engine can work in parallel in multiple threads.
  • Readability is important.
  • License must be compatible with closed-source projects.

I like Python for its readablity. I am also have more experience with Python than other scripting languages. However CPython is not multi-threaded, and IronPython requires hosting the CLR and a compatible language (C++/CLI or C#).

You might consider embedding a popular JavaScript engine. Not only will they be fast and well-supported, but so many people know how to program in JavaScript that it will be easily adopted and read by a large audience.

According to this answer the SpiderMonkey engine is thread-safe, while Google/Chrome's V8 may not be.

How to implement pause (and more) functionality?

12 votes

My apologies beforehand for the length of the question, I didn't want to leave anything out.

UPDATE: I added an update all the way at the bottom (still looking for an answer)

Some background information

I'm trying to automate a data entry process by writing a Python application that uses the Windows API to simulate keystrokes, mouse movement and window/control manipulation. I have to resort to this method because I do not (yet) have the security clearance required to access the datastore/database directly (e.g. using SQL) or indirectly through a better suited API. Bureaucracy, it's a pain ;-)

The data entry process involves the correction of sales orders due to changes in article availability. The unavailable articles are either removed from the order or replaced by another suitable article.

Initially I want a human to be able to monitor the automatic data entry process to make sure everything goes right. To achieve this I slow down the actions on the one hand but also inform the user of what is currently going on through a pinned window.

The actual question

To allow the user to halt the automation process I'm registering the Pause/Break key as a hotkey and in the handler I want to pause the automation functionality. However, I'm currently struggling to figure out a way to properly pause the execution of the automation functionality. When the pause function is invoked I want the automation process to stop dead in its tracks, no matter what it is doing. I don't want it to even execute another keystroke.

UPDATE [23/01]: I actually want to do more than just pause, I want to be able to communicate with the automation process while it is running and request it to pause, skip the current sales order, give up completely and perhaps even more.

Can anybody show me The Right Way (TM) to achieve what I want?

Some more information

Here's an example of how the automation works (I'm using the pywinauto library):

from pywinauto import application
app = application.Application()
app.start_("notepad")
app.Notepad.TypeKeys("abcdef")

UPDATE [25/01]: After a few days of working on my application I've noticed I don't really use pywinauto that much, right now I'm only using it for finding window and then I directly use SendKeysCtypes.SendKeys to simulate keyboard input and win32api functions to simulate mouse input.

What I've found out so far

Here are a few methods I've come across so far in my search for an answer:

  1. I could separate the automation functionality and the interface + hotkey listener in two separate processes. Let's refer to the former as "automator" and the latter as "manager". The manager can then pause the execution of the automator by sending the process a SIGSTOP signal and unpause it using the SIGCONT signal (or the Windows equivalents through SuspendThread/ResumeThread).

    To be able to update the user interface the automator will need to inform the manager of its progression through some sort of an IPC mechanism.

    Cons:

    • Would using SIGSTOP not be a little harsh? Would it even work properly? Lots of people seem to be advising against it and even calling it "dangerous".

    • I am worried that implementing the IPC mechanism is going to be a bit complicated. On the other hand, I have worked with DBus which wouldn't be too hard to implement.

  2. The second method and one that lots of people seem to be suggesting involves using threads and essentially boils down to the following (simplified):

    while True:
        if self.pause: # pause
        # Do the work...
    

    However, doing it this way it seems it will only pause after there is no more work to do. The only way I see this method would work would be to divide the work (the entire automation process) into smaller work segments (i.e. tasks). Before starting on a new task the worker thread would check if it should pause and wait.

    Cons:

    • Seems like an implementation to divide the work into smaller segments, such as the one above, would be very ugly code wise (aesthetically).

      The way I imagine it, all statements would be transformed to look something like: queue.put((function, args)) (e.g. queue.put((app.Notepad.TypeKeys, "abcdef"))) and you'd have the automating process thread running through the tasks and continuously checking for the pause state before starting a task. That just can't be right...

    • The program would not actually stop dead in its tracks, but would first finish a task (however small) before actually pausing.

Progress made

UPDATE [23/01]: I've implemented a version of my application using the first method through the mentioned SuspendThread/ResumeThread functionality. So far this seems to work very nicely and also allows me to write the automation stuff just like you'd write any other script. The only quirk I've come across is that keyboard modifiers (CTRL, ALT, SHIFT) get "stuck" while paused. Something I can probably easily work around.

I've also written a test using the second method (threads and signals/message passing) and implemented the pause functionality. However, it looks really ugly (both checking for the pause flag and everything related to the "doing the work"). So if anybody can show me a proper example of something similar to the second method I'd appreciate it.

Related questions

I don't know pywinauto. But I'll assume that you have something like an Application class which you obtain and have methods like SendKeys/SendMouseEvent/etc to do things.

Create your own MyApplication class which holds a reference to pywinauto's application class. Provide the same methods but before each method check whether a pause event has occurred. If it has, you can jump into code which handles the pause event. That way you are checking for a pause every time you cause an event, but this all is handled by the one class without putting pause all over your code.

Once you've detected the pause you can handle it any way you like. For example, you can throw an exception to force giving up on the current task.

How to create a snowstorm on your Windows desktop?

11 votes

Practical uses aside, how (if it is possible at all) could you create a "snowing" effect on your desktop PC running Windows? Preferably with nothing but raw C/C++ and WinAPI.

The requirements for the snow are:

  • Appears over everything else shown (Note: always-on-top windows may get on top of snow still, that's OK. I understand that there can be no "absolute on top" flag for any app)
  • Snowflakes are small, possibly simple dots or clusters of a few white pixels;
  • Does not bother working with the computer (clicking a snowflake sends the click through to the underlying window);
  • Plays nicely with users dragging windows;
  • Multi-monitor capable.

Bonus points for any of the following features:

  • Snow accumulates on the lower edge of the window or the taskbar (if it's at the bottom of the screen);
  • Snow accumulates also on top-level windows. Or perhaps some snow accumulates, some continues down, accumulating on every window with a title bar;
  • Snow accumulated on windows gets "shaken off" when windows are dragged;
  • Snow accumulated on taskbar is aware of the extended "Start" button under Vista/7.
  • Snowflakes have shadows/outlines, so they are visible on white backgrounds;
  • Snowflakes have complex snowflike-alike shapes (they must still be tiny).
  • Clicking on a snowflake does send the click through to the underlying window, but the snowflake evaporates with a little cool animation;

Most of these effects are straightforward enough, except the part where snow is click-through and plays nicely with dragging of windows. In my early days I've made an implementation that draws on the HDC you get from GetDesktopWindow(), which was click-through, but had problems with users dragging windows (snowflakes rendered on them got "dragged along").

The solution may use Vista/7 Aero features, but, of course, a universal solution is preferred. Any ideas?

For the sake of brevity and simplicity, this answer has been trimmed to a limited set of requirements. It is trivial to expand this and make it more robust.

This answer uses WPF on Windows XP. It should work on up to 2 monitors, and should work on other Windows systems as well.

It starts with a simple window:

<Window x:Class="TestDump.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" WindowStartupLocation="Manual" Loaded="Window_Loaded"
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
>
    <Grid x:Name="FieldOfSnow"/>
</Window>

To this window, we will add Snowflakes defined as follows:

<UserControl x:Class="TestDump.SnowFlake"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="5" Width="5">
    <Border Background="White" CornerRadius="2" BorderThickness="1" BorderBrush="LightGray"/>
</UserControl>

The snowflakes have the default UserControl code-behind with no changes.

Finally, the Window CodeBehind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Interop;

namespace TestDump
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private TimeSpan _lastRender;

        public Window1()
        {
            InitializeComponent();
            _lastRender = TimeSpan.FromTicks(0);
            CompositionTarget.Rendering += SnowflakeTick;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.Topmost = true;
            this.Top = 0;
            this.Left = 0;

            this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
            this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;

            if (System.Windows.Forms.SystemInformation.MonitorCount == 2)
            {
                System.Drawing.Rectangle SecondScreenArea = System.Windows.Forms.Screen.AllScreens[1].Bounds;

                this.Width += SecondScreenArea.Width;
                this.Height = this.Height > SecondScreenArea.Height ? this.Height : SecondScreenArea.Height;
            }
        }

        public const int WS_EX_TRANSPARENT = 0x00000020;
        public const int GWL_EXSTYLE = (-20);

        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr hwnd, int index);

        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            // Get this window's handle
            IntPtr hwnd = new WindowInteropHelper(this).Handle;

            // Change the extended window style to include WS_EX_TRANSPARENT
            int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
            SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
        }

        List<TranslateTransform> Flakes = new List<TranslateTransform>();
        Random rand = new Random();

        private void SnowflakeTick(object sender, EventArgs e)
        {
            RenderingEventArgs renderingArgs = (RenderingEventArgs)e;
            TimeSpan dTime = (renderingArgs.RenderingTime - _lastRender);
            double deltaTime = dTime.TotalMilliseconds;
            _lastRender = renderingArgs.RenderingTime;

            if ( _lastRender.Milliseconds < deltaTime)
            {
                TranslateTransform SnowPos = new TranslateTransform(this.Width * rand.Next(1000) / 1000.0 - this.Width/2, -this.Height/2);

                SnowFlake sf = new SnowFlake();
                sf.RenderTransform = SnowPos;

                // The flakes are centered when added, so all positions must be translated with this in mind.
                FieldOfSnow.Children.Add(sf);
                Flakes.Add(SnowPos);
            }

            foreach (TranslateTransform Flake in Flakes)
            {
                double ScreenHeight = this.Height / 2 - 2;

                if (Flake.Y < ScreenHeight)
                {
                    Flake.Y += deltaTime / 50;
                }
            }
        }
    }
}

I had to use a bit of forms code to get the multiscreen stuff, and I had to include the references to the Assemblies in my project.

I haven't tested it much, but it does work on my system, and the snow sits at the bottom of the screen when done.

I used this reference for the click through behavior.

A more dedicated fellow than I should be able to adapt this, plus some edge detection to the task of getting the snow to sit elsewhere.

Please be aware that snowflakes are never cleaned up in this example, and after running it long enough, you may notice some slowdown.

Have Fun!

how to count bytes sent and received per TCP connection (system-wide)?

10 votes

e.g. recent versions of TCPView has such functionality: showing bytes sent/received per TCP connection (counting starts when TCPView is launched). is it possible w/o packet sniffering? does windows provides any API for this? I haven't found such Performance Counter

how to enumerate all connections are described here

EDIT: does TDI help to receive per-socket transfer statistics? NetBIOS? any links where to dig?

I want to implement this function also, so I reverse tcpview 3.0.2.

I found, tcpview use a WMI performance counter MSNT_TcpIpInformation.

But MSNT_TcpIpInformation is not supported in xp and 2003 officially.

here is the description, you can reference to. http://www.scriptinternals.com/new/us/support/Internal/WMI_MSNT_TcpIpInformation.htm

by the way, MSNT_TcpIpInformation have no information about packets, so tcpview just increment sent and revd packets everytime. here is the disassemble:

CPU Disasm
Address   Hex dump          Command                                           Comments
0040B41B  |.  83E8 02       SUB EAX,2                                         ; Switch (cases 2..3, 3 exits)
0040B41E  |.  74 29         JE SHORT 0040B449
0040B420  |.  83E8 01       SUB EAX,1
0040B423  |.  75 40         JNE SHORT 0040B465
0040B425  |.  8B57 1C       MOV EDX,DWORD PTR DS:[EDI+1C]                     ; Case 3 of switch Tcpview.40B41B
0040B428  |.  0196 90060000 ADD DWORD PTR DS:[ESI+690],EDX
0040B42E  |.  119E 94060000 ADC DWORD PTR DS:[ESI+694],EBX
0040B434  |.  8386 C0060000 ADD DWORD PTR DS:[ESI+6C0],1
0040B43B  |.  119E C4060000 ADC DWORD PTR DS:[ESI+6C4],EBX
0040B441  |.  5E            POP ESI
0040B442  |.  5F            POP EDI
0040B443  |.  5D            POP EBP
0040B444  |.  5B            POP EBX
0040B445  |.  83C4 3C       ADD ESP,3C
0040B448  |.  C3            RETN
0040B449  |>  8B47 1C       MOV EAX,DWORD PTR DS:[EDI+1C]                     ; Case 2 of switch Tcpview.40B41B
0040B44C  |.  0186 78060000 ADD DWORD PTR DS:[ESI+678],EAX
0040B452  |.  119E 7C060000 ADC DWORD PTR DS:[ESI+67C],EBX
0040B458  |.  8386 A8060000 ADD DWORD PTR DS:[ESI+6A8],1
0040B45F  |.  119E AC060000 ADC DWORD PTR DS:[ESI+6AC],EBX
0040B465  |>  5E            POP ESI                                           ; Default case of switch Tcpview.40B41B
0040B466  |.  5F            POP EDI

How to install pip on windows?

10 votes

pip is a replacement for easy_install. But I will install pip using easy_install on Windows. Is there a better way?

As you mention pip doesn't include an independent installer, but you can install it easily with its predecessor easy_install.

So:

  1. Download the latests pip version from here: http://pypi.python.org/pypi/pip#downloads
  2. Uncompress it
  3. Download the latest easy installer for Windows: (download the .exe at the bottom of http://pypi.python.org/pypi/setuptools ). Install it.
  4. go to the uncompressed pip directory and: python setup.py install
  5. Add your python c:\Python2x\Scripts to the path

You are done.

Now you can use pip install package to easily install packages as in Linux :)

How Can I Hook a Youtube Video (Flash Player?) To Slow Down Playback?

10 votes

The only good software I know which can decelerate and accelerate the playback of a YouTube video in any browser without first downloading it (because that would be cumbersome), is Enounce MySpeed.

Unfortunately, this software is not free, and my trial version ran out. I was playing around with its registry settings and noticed a few keys:

ProgramsToHook: iexplore.exe;firefox.exe;plugin-container.exe;chrome.exe;safari.exe;opera.exe;maxthon.exe;feeddemon.exe;realplay.exe;flvplayer.exe;flv player.exe;flock.exe;adobe media player.exe
UseFlashAdapter: 1
LLModules: ole32.dll;nspr4.dll;chrome.exe;realplay.exe;objb3201.dll;oleaut32.dll;rpflashplayer.dll
ModulesToIntercept: flash10*;flash9*;npswf32.dll;gcswf32.dll;fldbg10*;flashplayer.3.1.1k.ocx;adobe media player.exe

Based on the names and values of these registry keys, I'm guessing the MySpeed software hooks some function(s) in the listed modules (but modules are or aren't the same as DLLs?..) and does so for each process listed in ProgramsToHook. This is what I don't understand. What is the concept of the MySpeed software. Obviously it's hooking something, but I'm not too familiar with the intricacies of Windows hooks so I came to ask you experts. I'm thinking if I can understand how this hook process works, I can make my own version of the software using EasyHook, which is a fantastic .NET library to perform user-mode and kernel-mode hooks.

I thought that Windows user-mode hooking goes something like this. You choose one function in one DLL, and you intercept that function (a.k.a hook) in one process you want. If you want to hook the DLL in multiple processes, you just have to repeat the procedure for each process.

And then kernel-mode hooking is just choosing one function in one DLL and intercepting that function in every process that calls it (hence kernel-mode). But surely there are tons of ways to hook; I'm not too sure on whats the difference between these two hooks and DLL injection either.

So the point is, I'd like to know how MySpeed works. What is their hooking concept? If I can know this then I can make such a software in .NET!

Thanks in advance.

I can't provide you with an accurate explanation as I don't know the API calls or capabilites, but it goes something like this: You app looks for iexplore.exe where it intercepts calls to certain modules. The module is mainly flash player. Flash has support for playing the video slower so you modify the call from iexplore.exe (JavaScript play button on webpage) or make an additional call to set playback speed.

What you need to do:

  • Use this tool to check what is actually happening: http://www.nektra.com/products/deviare-api-hook-windows/
  • Learn how to ask Flash Player to slow down a video (probably in Flash API docs). One Simple approach could be to see what MySpeed is actually doing using the Deviare API hook tool.
  • Write a program that replicates this procedure. It involves intercepting messages sent from one handle (iexplore.exe) to another (flash .dll). This can't be done externally, it has to be done internally, so this may be of help: http://www.codeproject.com/KB/threads/winspy.aspx

On hooks: http://msdn.microsoft.com/en-gb/library/ms644960.aspx

I don't think many people has done this in C#, so it could offer a challenge. I would though be interested in the progress (obstacles) if you have a blog or something to share the gory details on. :)

EDIT: The Deviare API Hook software seems not only to spy on calls, but also allow you to intercept them. So its a all-in-one package for your needs. :)
EDIT2: Relevant question: How do I intercept messages being sent to a window?

Rounding differences on Windows vs Unix based system in sprintf

9 votes

I have problem on UNIX based systems sprintf does not round up properly value.

For example

double tmp = 88888888888885.875
char out[512];

Thats 88,888,888,888,885.875 just to be easier on eyes. I am giving such specific and big example because it seems it works fine on smaller numbers.

I am trying to use it in following way

sprintf(out, "%021.2f", tmp);
printf("out = %s\n", tmp);

On windows this results in:

out = 000088888888888885.88

On for example AIX, but shows in Linux as well:

out = 000088888888888885.87

Why is this happening? Any ideas and how to make it behave same way on Win/Unix

Thanks

There is a bug report for glibc with a problem very similar to yours. The main conclusion (in comment 46) here is that double is not a 15-decimal-digit number and you should not expect it to work like that.

As a workaround you can add something small to your numbers to make them round better. But this solution is not general because it depends on number ranges you deal with.

Another workaround can be multiplying to prepare them for rounding, then rounding (e.g. 2597.625*100 = 259762.5 -> 259763 = 2597.63*100)

However I think there must be smarter workarounds.

How can I programatically determine which application is locking a file?

9 votes

Possible Duplicate:
How do I find out which process is locking a file using .NET?

I want to copy a file but it is locked by another application, so a FileInUseException is thrown. I would like to tell the user which application is locking the file I'm trying to copy. Is there a way in the .NET Framework to do this? Without this knowledge, I'm resorting to telling the users to use the Unlocker application.

You could try the code provided in this question over here, or look at other suggestions here.

The general approach is to enumerate the handles of all processes, get the file paths of those handles, and compare against the file you're interested in.

But a problem with this approach is that even if you can determine that the file is locked and which application has the file lock then you will still have to cope with race conditions, for example...

one millisecond later

  • the file is not locked
  • the application that did hold the lock is now not

then two milliseconds later

  • the file is locked (again)
  • a different application has the lock

then three milliseconds later

  • the file is still locked
  • yet another app has the lock

...etc

One suggestion is to attempt to get the file handle in your app, and catch the exception when you can't.

 try
 {
    using (Stream stream = new FileStream("MyFilename.txt"))
   {
   }
 } catch {
   //check here why it failed and ask user to retry if the file is in use.
}

Of course this won't help identify the culprit(s) but at least you have a safer way of attempting to access the file.

Where does "Your Kitten of Death awaits" come from?

8 votes

If you run SBCL (at least on Windows, I use CLISP at home), you get the message, "Your Kitten of Death awaits." I suspect that this has something to do with some form of inside joke (like Super Cow Powers). I've tried Googling and I have found nothing particularly useful (I suppose that it is mentioned elsewhere on the 'net is of some, if not much, use).

If this seems more of a SuperUser or ServerFault question, please let me know and I will ask on their forums instead.


UPDATE:

It seems that the origin of this quote is from a commit by Christopher Rhodes to version 1.54 of the original source (thanks to Daniel A. White for finding the fild name). I'm not sure if that will prove useful, but it is an additional avenue to approach this query.

Here is a diff that has it, but its been removed in this patch.

http://www.peerweb.nl/sbcl/sbcl-1.0.14.10-windows.patch

How to split a huge folder?

8 votes

We have a folder on Windows that's ... huge. I ran "dir > list.txt". The command lost response after 1.5 hours. The output file is about 200 MB. It shows there're at least 2.8 million files. I know the situation is stupid but let's focus the problem itself. If I have such a folder, how can I split it to some "manageable" sub-folders? Surprisingly all the solutions I have come up with all involve getting all the files in the folder at some point, which is a no-no in my case. Any suggestions?

Thank Keith Hill and Mehrdad. I accepted Keith's answer because that's exactly what I wanted to do but I couldn't quite get PS working quickly.

With Mehrdad's tip, I wrote this little program. It took 7+ hours to move 2.8 million files. So the initial dir command did finish. But somehow it didn't return to console.

namespace SplitHugeFolder
{
    class Program
    {
        static void Main(string[] args)
        {
            var destination = args[1];

            if (!Directory.Exists(destination))
                Directory.CreateDirectory(destination);

            var di = new DirectoryInfo(args[0]);

            var batchCount = int.Parse(args[2]);
            int currentBatch = 0;

            string targetFolder = GetNewSubfolder(destination);

            foreach (var fileInfo in di.EnumerateFiles())
            {
                if (currentBatch == batchCount)
                {
                    Console.WriteLine("New Batch...");
                    currentBatch = 0;
                    targetFolder = GetNewSubfolder(destination);
                }

                var source = fileInfo.FullName;
                var target = Path.Combine(targetFolder, fileInfo.Name);
                File.Move(source, target);
                currentBatch++;
            }
        }

        private static string GetNewSubfolder(string parent)
        {
            string newFolder;
            do
            {
                newFolder = Path.Combine(parent, Path.GetRandomFileName());
            } while (Directory.Exists(newFolder));
            Directory.CreateDirectory(newFolder);
            return newFolder;
        }
    }
}

I use Get-ChildItem to index my whole C: drive every night into c:\filelist.txt. That's about 580,000 files and the resulting file size is ~60MB. Admittedly I'm on Win7 x64 with 8 GB of RAM. That said, you might try something like this:

md c:\newdir
Get-ChildItem C:\hugedir -r | 
    Foreach -Begin {$i = $j = 0} -Process { 
        if ($i++ % 100000 -eq 0) { 
            $dest = "C:\newdir\dir$j"
            md $dest
            $j++ 
        }
        Move-Item $_ $dest 
    }

The key is to do the move in a streaming manner. That is, don't collect up all the Get-ChildItem results into a single variable and then proceed. That would require all 2.8 million FileInfos to be in memory at once. Also, if you use the Name parameter on Get-ChildItem it will output a single string containing the file's path relative to the base dir. Even then, perhaps this size will just overwhelm the memory available to you. And no doubt, it will take quite a while to execute. IIRC correctly, my indexing script takes several hours.

If it does work, you should wind up with c:\newdir\dir0 thru dir28 but then again, I haven't tested this script at all so your mileage may vary. BTW this approach assumes that you're huge dir is a pretty flat dir.

Update: Using the Name parameter is almost twice as slow so don't use that parameter.

Ruby on Rails development on windows

7 votes

I've been planning on developing a rails project on windows. I've heard that the framework wasn't tested on windows (at least not the testing framework)

does anyone have any real experience with rails on windows? are there any known bugs when running on windows? does the testing framework work on windows?

I've been developing a Rails website on Windows & Mac (depending on where I am at the time) for a few months now and, in general, I haven't run into to many problems. Here's what I know:

The new Ruby 1.9.2 installer for Windows is nice because it comes with RubyGems (which a vague memory tells me was difficult before). That's what I'm using. I haven't been able to get the ruby-debug19 gem to install correctly on windows. So, I just comment that out in my Gemfile on my Windows computer. Other than that, I haven't had any issues.

With that said, however, I love developing on my Mac so much more than I do on Windows. I haven't found an editor that I love for Rails development on Windows (currently using Notepad++ with Explorer plugin), using git is not as nice on Windows, and I just really don't like the Windows Command Prompt (I know there are other options, but still).