# Outlook and win32 service

**URL:** <https://www.ruby-forum.com/t/outlook-and-win32-service/134167>\
**Category:** Ruby\
**Created:** [April 8, 2008, 3:51pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167 "2008-04-08T15:51:03Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 8, 2008, 3:51pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/1 "2008-04-08T15:51:03Z")

</div>

Hi all,

i detail out an issue i am facing while trying to read messages from  
outlook via a windows service.

The goal of the code is to scan outlook inbox every 10 minutes and if  
any specified file attachment is found … save it.

The code will be installed as an windows service and scan for the  
email automatically.

The service code is fine and runs in background as well but as I call  
outlook via win32ole from the service mainloop it does not give me  
the inbox with any item.

Can any one lead me to the problem??

# the service code it works like a champ

require ‘win32/service’  
include Win32

puts 'VERSION: ’ + Service::VERSION

SERVICE\_NAME = ‘Kpi-file-Scanner’  
SERVICE\_DISPLAYNAME = ‘An-outlook-scanner’

cmd = ‘c:\instantrails\ruby\bin\ruby’

cmd += ‘“C:\instantrails\rails\_apps\kpi\vendor\service  
\outlookpull.rb”’

raise ArgumentError, ‘No argument provided’ unless ARGV[0]

case ARGV[0].downcase  
when ‘install’

```
 svc= Service.new(SERVICE_NAME, nil,{
  :service_type => Service::WIN32_OWN_PROCESS,
  :description => SERVICE_DISPLAYNAME,
  :start_type => Service::AUTO_START,
  :error_control => Service::ERROR_NORMAL,
  :binary_path_name => cmd,
  :load_order_group => 'Network',
  :dependencies => ['W32Time','Schedule'],
  :display_name => 'Kpi-file-Scanner'}
  )

  puts 'Service ' + SERVICE_NAME + ' installed'

```

when ‘start’  
if Service.status(SERVICE\_NAME).current\_state != ‘running’

```
     Service.start(SERVICE_NAME)
     while Service.status(SERVICE_NAME).current_state != 'running'
        puts 'One moment...' +

```

# Service.status(SERVICE\_NAME).current\_state sleep 1 end puts ‘Service ’ + SERVICE\_NAME + ’ started’ else puts ‘Already running’ end when ‘stop’ if Service.status(SERVICE\_NAME).current\_state != ‘stopped’ Service.stop(SERVICE\_NAME) while Service.status(SERVICE\_NAME).current\_state != ‘stopped’ puts ‘One moment…’ + Service.status(SERVICE\_NAME).current\_state sleep 1 end puts ‘Service ’ + SERVICE\_NAME + ’ stopped’ else puts ‘Already stopped’ end when ‘uninstall’, ‘delete’ if Service.status(SERVICE\_NAME).current\_state != ‘stopped’ Service.stop(SERVICE\_NAME) end while Service.status(SERVICE\_NAME).current\_state != ‘stopped’ puts ‘One moment…’ + Service.status(SERVICE\_NAME).current\_state sleep 1 end Service.delete(SERVICE\_NAME) puts ‘Service ’ + SERVICE\_NAME + ’ deleted’ when ‘pause’ if Service.status(SERVICE\_NAME).current\_state != ‘paused’ Service.pause(SERVICE\_NAME) while Service.status(SERVICE\_NAME).current\_state != ‘paused’ puts ‘One moment…’ + Service.status(SERVICE\_NAME).current\_state sleep 1 end puts ‘Service ’ + SERVICE\_NAME + ’ paused’ else puts ‘Already paused’ end when ‘resume’ if Service.status(SERVICE\_NAME).current\_state != ‘running’ Service.resume(SERVICE\_NAME) while Service.status(SERVICE\_NAME).current\_state != ‘running’ puts ‘One moment…’ + Service.status(SERVICE\_NAME).current\_state sleep 1 end puts ‘Service ’ + SERVICE\_NAME + ’ resumed’ else puts ‘Already running’ end else raise ArgumentError, 'unknown option: ’ + ARGV[0] end

now the outlookpull.rb code that is called by this service

===================================================  
LOG\_FILE = “C:\instantrails\rails\_apps\kpi\vendor\service  
\test.log”

begin  
require “C:\instantrails\ruby\lib\ruby\gems\1.8\gems  
\actionpack-2.0.2\lib\action\_controller.rb”  
require “C:\instantrails\rails\_apps\kpi\app\controllers  
\application.rb”  
require “C:\instantrails\rails\_apps\kpi\app\controllers  
\kpimumbai\_controller.rb”  
File.open(LOG\_FILE, “a+”){ |f| f.puts “kpimumbai\_controller.rb  
required” }  
require ‘win32/service’  
require ‘win32/daemon’  
include Win32  
require ‘win32ole’  
require “parsedate.rb”  
include ParseDate

class Daemon

```
  def service_init
     @a=KpimumbaiController.new
      sleep 10
  end

  def service_main
     msg = 'service_main entered at: ' + Time.now.to_s
     File.open(LOG_FILE, "a+"){ |f| f.puts msg }
     #@first_entry = true
     while running?
        if state == RUNNING
           msg = 'running state entered at : ' + Time.now.to_s
           File.open(LOG_FILE, "a+"){ |f| f.puts msg }
           begin
           #@tick.refresh(@first_entry,@sqlconnect)
           #@first_entry = false
               #require 'win32ole'

           #we will get the time of the last parsed message and
           #will go in only if the message timing is after that of

```

the last parsed  
#message time  
File.open(LOG\_FILE, “a+”){ |f| f.puts “just before  
readlines” }  
last\_time=IO.readlines(“C:\instantrails\rails\_apps  
\kpi\vendor\service\spawntime.log”)  
last\_time=last\_time.to\_s.chomp  
File.open(LOG\_FILE, “a+”){ |f| f.puts  
“=====last\_time:#{last\_time}” }

```
               if last_time.to_s == "nil"
                 last_time="1971/10/04 19:03:24"
               end
               @outlook = WIN32OLE.new('Outlook.Application')
              @mapi = @outlook.GetNameSpace('MAPI')
             @inbox = @mapi.GetDefaultFolder(6)
             @file_c=1

               arr_last_time =

```

parsedate(last\_time.to\_s).delete\_if{|x|x==“nil”}

```
               File.open(LOG_FILE, "a+"){ |f| f.puts

```

“=====arr\_last\_time:#{arr\_last\_time}” }

timed\_last\_time=Time.mktime(arr\_last\_time[0],arr\_last\_time[1],arr\_last\_time[2],arr\_last\_time[3],arr\_last\_time[4],arr\_last\_time[5])

```
               File.open(LOG_FILE, "a+"){ |f| f.puts

```

“====timed\_last\_time:#{timed\_last\_time}” }

```
               File.open(LOG_FILE, "a+"){ |f|

```

f.puts"#{@inbox.UnreadItemCount}:Unread Messages" }  
File.open(LOG\_FILE, “a+”){ |f| f.puts  
“#{@inbox.Items.Count}: Messages” }  
begin  
@inbox.Items.each do |message|

```
                  File.open(LOG_FILE, "a+"){ |f| f.puts

```

“====mesage time:#{message.ReceivedTime}” }  
time\_of\_the\_message =  
parsedate(message.ReceivedTime)  
#this gives us the array containing the time  
timed\_time\_of\_the\_message =  
Time.mktime(time\_of\_the\_message[0],time\_of\_the\_message[1],time\_of\_the\_message[2],time\_of\_the\_message[3],time\_of\_the\_message[4],time\_of\_the\_message[5])  
#we will compare this time with the last time  
object and go in for looking  
#onto attachment if this is newer  
File.open(LOG\_FILE, “a+”){ |f| f.puts  
“time difference:#{timed\_time\_of\_the\_message-timed\_last\_time}”}  
if timed\_time\_of\_the\_message \>  
timed\_last\_time  
message.Attachments.each do |  
attachment|

filepattern=attachment.fileName.to\_s.index(/NBH\_|BBH\_/)  
if filepattern !=  
nil  
File.open(LOG\_FILE,  
“a+”){ |f| f.puts “======#{attachment.fileName.to\_s}”}

```
                                               temp_filename = "C:\

```

\instantrails\rails\_apps\kpi\vendor\service\temp  
#{attachment.FileName}"  
Dir.foreach(“C:  
\instantrails\rails\_apps\kpi\vendor\service\temp\”) { |x|  
File.delete(“C:\instantrails\rails\_apps\kpi\vendor\service\temp  
“+ x) if x!= “.” && x!=”…” }

attachment.SaveAsFile(temp\_filename)  
#we will now call  
the fileupdater method of kpimumbaicontroller object

@a.fileupdateupdater(temp\_filename)

```
                                               @file_c +=1
                                               end
                                    end
                            else
                            next
                            end

                   timed_last_time=timed_time_of_the_message
                  end
                  rescue Exception => err
                    File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the

```

error at inner begin: ’ + err }

```
                     raise

                   end

           msg = 'mailbox spawn succ at : ' + Time.now.to_s
           File.open(LOG_FILE, "a+"){ |f| f.puts msg }

           rescue Exception => err
                    File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the

```

error at outer begin: ’ + err }  
#close @sqlconnection  
raise  
#msg = 'mail box spawn FAILED at : ’ +  
Time.now.to\_s  
#File.open(LOG\_FILE, “a+”){ |f| f.puts msg }  
end  
#finally after every spawn we need to update the last time  
stamp entry in the spawn file  
File.open(“C:\instantrails\rails\_apps\kpi\vendor  
\service\spawntime.log”, “w+”){ |f| f.puts timed\_last\_time }  
#outlook.close  
sleep 180  
else  
msg = 'non running state entered at : ’ +  
Time.now.to\_s  
File.open(LOG\_FILE, “a+”){ |f| f.puts msg }  
sleep 0.5  
end  
end

```
     File.open(LOG_FILE, "a+"){ |f| f.puts "STATE: #{state}" }

     msg = 'service_main left at: ' + Time.now.to_s
     File.open(LOG_FILE, "a+"){ |f| f.puts msg }
  end

  def service_stop

     msg = "Received stop signal at: " + Time.now.to_s
     File.open(LOG_FILE, "a+"){ |f| f.puts msg }
  end

  def service_pause
     msg = "Received pause signal at: " + Time.now.to_s
     File.open(LOG_FILE, "a+"){ |f| f.puts msg }
  end

  def service_resume
     msg = "Received resume signal at: " + Time.now.to_s
     File.open(LOG_FILE, "a+"){ |f| f.puts msg }
  end

```

end

svc=Daemon.new  
svc.mainloop

rescue Exception =\> err  
File.open(LOG\_FILE, “a+”){ |fh| fh.puts 'Daemon failure: ’ + err }

raise  
end

==================================================

Sorry for a long code…

# The problem is that my log file loooks like this

# kpimumbai\_controller.rb required service\_main entered at: Tue Apr 08 17:30:24 +0530 2008 running state entered at : Tue Apr 08 17:30:24 +0530 2008 just before readlines =====last\_time:Mon Oct 04 19:03:24 +0530 1971 =====arr\_last\_time:197110419324+05301 ====timed\_last\_time:Mon Oct 04 19:03:24 +0530 1971 0:Unread Messages 0: Messages mailbox spawn succ at : Tue Apr 08 17:30:24 +0530 2008

the inbox messagecount is returning 0 messages.

while if i run it without any service deamon via simple code like this

require ‘win32ole’  
outlook = WIN32OLE.new(‘Outlook.Application’)  
mapi = outlook.GetNameSpace(‘MAPI’)  
inbox = mapi.GetDefaultFolder(6)  
file\_c=1

# #methods = [] #arrival\_time=inbox.Items(1).ReceivedTime #b=arrival\_time.to\_a #puts arrival\_time #require “parsedate.rb” #include ParseDate #formatted\_date=parsedate(arrival\_time) #p formatted\_date puts “#{inbox.UnreadItemCount}:so many unread messages” puts “#{inbox.Items.Count}:so many messages”

# i get output like a champ

# 484:so many unread messages 11398:so many messages

i am battling it out for last couple of days to find why.  
and i need help badly.

Br

Rajib

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 8, 2008, 4:22pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/2 "2008-04-08T16:22:54Z")

</div>

On Tue, Apr 8, 2008 at 3:50 PM, BENI [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> The service code is fine and runs in background as well but as I call  
> outlook via win32ole from the service mainloop it does not give me  
> the inbox with any item.

Hi,

quick hint without reading your code: do you have permissions to read  
the mailbox?  
Or, are you really reading the mailbox you think you are reading?

Usually services run under SYSTEM account, so you may have to change  
it to run under  
you user account to read your mails. Alternatively, you can use runas  
command to exec script under different account.

J.

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 8, 2008, 9:36pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/3 "2008-04-08T21:36:52Z")

</div>

Who is the service running as? It’s going to need to run as the owner  
of the inbox for this to stand a chance. Is this exchange server or pop  
mail? If it’s exchange server, remember that it uses integrated  
authorization; so again, you’ll need the correct user as the service’s  
login user. If it’s pop, it’s just because it’s reading the wrong set  
of things in “Documents and Settings” and maybe the registry.

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 9, 2008, 1:50pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/4 "2008-04-09T13:50:39Z")

</div>

On Apr 9, 12:34 am, “Nation, Carey” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Who is the service running as? It’s going to need to run as the owner  
> of the inbox for this to stand a chance. Is this exchange server or pop  
> mail? If it’s exchange server, remember that it uses integrated  
> authorization; so again, you’ll need the correct user as the service’s  
> login user. If it’s pop, it’s just because it’s reading the wrong set  
> of things in “Documents and Settings” and maybe the registry.

Thanks for your inputs

1\>I am using office2003 and outlook2003 in it. So I am using pop mail  
I guess.

Now how do i configure my service code’s service login user?

do i have add this part of the code?

:service\_start\_name =\> ‘SomeDomain\User’ onto my svc object?

svc= Service.new(SERVICE\_NAME, nil,{  
:service\_type =\> Service::WIN32\_OWN\_PROCESS,  
:description =\> SERVICE\_DISPLAYNAME,  
:start\_type =\> Service::AUTO\_START,  
:error\_control =\> Service::ERROR\_NORMAL,  
:binary\_path\_name =\> cmd,  
:load\_order\_group =\> ‘Network’,  
:dependencies =\> [‘W32Time’,‘Schedule’],  
:display\_name =\> ‘Kpi-file-Scanner’}  
)

2\>Also I found this link [Outlook Object Model cannot run in a Windows service - Outlook | Microsoft Learn](http://support.microsoft.com/kb/237913) which  
says (The Outlook Object Model is unsuitable to run in a Windows  
service) that is very discouraging.

3\>What I am unable to still understand when i run the following

require ‘win32ole’  
outlook = WIN32OLE.new(‘Outlook.Application’)  
mapi = outlook.GetNameSpace(‘MAPI’)  
inbox = mapi.GetDefaultFolder(6)  
file\_c=1  
puts “#{inbox.UnreadItemCount}:so many unread messages”  
puts “#{inbox.Items.Count}:so many messages”

… I get perfect ouput… and looking onto windows process i find  
oulook.exe running under SYSTEM …but still I get the right output.

…

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 9, 2008, 2:34pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/5 "2008-04-09T14:34:22Z")

</div>

On 9 Apr 2008, at 12:50, BENI wrote:

> > of things in “Documents and Settings” and maybe the registry.
> 
> Thanks for your inputs
> 
> 1\>I am using office2003 and outlook2003 in it. So I am using pop mail  
> I guess.

I don’t remember what your original task was, but have you considered  
using Net::POP?

> ```
> :service_type => Service::WIN32_OWN_PROCESS,
> 
> ```
> 
> says (The Outlook Object Model is unsuitable to run in a Windows  
> service) that is very discouraging.

I do not know the specifics, but doing my own work I recently ran into  
the issues of how sandboxed the services are.

> … I get perfect ouput… and looking onto windows process i find  
> oulook.exe running under SYSTEM …but still I get the right output.
> 
> …

You may be able to do this by hacking the User HIVE in order to  
authorize SYSTEM with access to the users registry, and then there’s a  
dual logon hack you can use to ensure that a SYSTEM logon will load  
the target users hive into memory. Sadly this is a major security  
issue that you will raise, and the process is very complicated  
(involving copying various hashes around under regedit32 running as  
SYSTEM iirc, and you might even need to sort out some UTF8 interface  
problems iirc). This is most typically used for laptop users that need  
local administrator rights, but cannot be administrators in the  
controlling domain. The users traditionally had two user accounts, but  
using the same technique one can effectively ‘log on’ as both users  
simultaneously.

Finally, I might also suggest that there’s no need to service this.  
You should be able to create either an outlook plugin or a new outlook  
‘launcher’ (using COM, almost as you have already done) in order to  
run this process whenever outlook is running. From this point you may  
then consider using a standard ‘daemonizing’ tool such as firedaemon  
(I’ve never used that, but I have seen it running ‘normal’ windows  
processes under a service wrapper) for solving the problem of service  
restrictions.

HTH

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 9, 2008, 4:21pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/6 "2008-04-09T16:21:15Z")

</div>

On 9 Apr 2008, at 14:37, Phillip G. wrote:

> into  
> | the issues of how sandboxed the services are.
> 
> Control Panel -\> Administrative Tools -\> Services.
> 
> Right click on the name of the service, click on the “Log on” tab, and  
> change the credentials to the correct ones.
> 
> Or: Run the script as Scheduled Task, instead…

That will not help with accessing user mode mounted devices (such as  
using subst, or certain network shares (read: parallels)).

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [April 9, 2008, 3:38pm UTC](https://www.ruby-forum.com/t/outlook-and-win32-service/134167/7 "2008-04-09T15:38:05Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

James T. wrote:  
|\> 2\>Also I found this link [Outlook Object Model cannot run in a Windows service - Outlook | Microsoft Learn](http://support.microsoft.com/kb/237913) which  
|\> says (The Outlook Object Model is unsuitable to run in a Windows  
|\> service) that is very discouraging.  
|  
| I do not know the specifics, but doing my own work I recently ran into  
| the issues of how sandboxed the services are.

Control Panel → Administrative Tools → Services.

Right click on the name of the service, click on the “Log on” tab, and  
change the credentials to the correct ones.

Or: Run the script as Scheduled Task, instead…

* * *

Phillip G.  
Twitter: [twitter.com/cynicalryan](http://twitter.com/cynicalryan)

~ - You know you’ve been hacking too long when…  
…you get a thank-you note from the local power company, along with a  
co-signer form for next month’s bill.  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.8 (MingW32)  
Comment: Using GnuPG with Mozilla - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iEYEARECAAYFAkf8xogACgkQbtAgaoJTgL+cdwCdH0u+4u46DywWwXEuwqpH/n24  
CSQAn3GT6/qTAho6OPGiROp8Y24oBY7W  
=jMOm  
-----END PGP SIGNATURE-----
