[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: outlook and win32 service

Nation, Carey

4/8/2008 7:35:00 PM

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.

-----Original Message-----
From: BENI [mailto:rajib.chakrabarti@googlemail.com]=20
Sent: Tuesday, April 08, 2008 9:50 AM
To: ruby-talk ML
Subject: outlook and win32 service

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
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
require 'win32/service'
include Win32

puts 'VERSION: ' + Service::VERSION


SERVICE_NAME =3D 'Kpi-file-Scanner'
SERVICE_DISPLAYNAME =3D 'An-outlook-scanner'

cmd =3D 'c:\instantrails\ruby\bin\ruby'

cmd +=3D '"C:\\instantrails\\rails_apps\\kpi\\vendor\\service\outlookpull.rb"'

raise ArgumentError, 'No argument provided' unless ARGV[0]

case ARGV[0].downcase
when 'install'


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


puts 'Service ' + SERVICE_NAME + ' installed'
when 'start'
if Service.status(SERVICE_NAME).current_state !=3D 'running'

Service.start(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state !=3D '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 !=3D 'stopped'
Service.stop(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state !=3D '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 !=3D 'stopped'
Service.stop(SERVICE_NAME)
end
while Service.status(SERVICE_NAME).current_state !=3D '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 !=3D 'paused'
Service.pause(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state !=3D '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 !=3D 'running'
Service.resume(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state !=3D '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
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
now the outlookpull.rb code that is called by this service

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
LOG_FILE =3D "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=3DKpimumbaiController.new
sleep 10
end

def service_main
msg =3D 'service_main entered at: ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
#@first_entry =3D true
while running?
if state =3D=3D RUNNING
msg =3D '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 =3D 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=3DIO.readlines("C:\\instantrails\\rails_apps
\\kpi\\vendor\\service\\spawntime.log")
last_time=3Dlast_time.to_s.chomp
File.open(LOG_FILE, "a+"){ |f| f.puts
"=3D=3D=3D=3D=3Dlast_time:#{last_time}" }

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


arr_last_time =3D
parsedate(last_time.to_s).delete_if{|x|x=3D=3D"nil"}

File.open(LOG_FILE, "a+"){ |f| f.puts
"=3D=3D=3D=3D=3Darr_last_time:#{arr_last_time}" }

=20
timed_last_time=3DTime.mktime(arr_last_time[0],arr_last_time[1],arr_last_=
t
ime[2],arr_last_time[3],arr_last_time[4],arr_last_time[5])

File.open(LOG_FILE, "a+"){ |f| f.puts
"=3D=3D=3D=3Dtimed_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
"=3D=3D=3D=3Dmesage time:#{message.ReceivedTime}" }
time_of_the_message =3D
parsedate(message.ReceivedTime)
#this gives us the array containing the time
timed_time_of_the_message =3D
Time.mktime(time_of_the_message[0],time_of_the_message[1],time_of_the_me
ssage[2],time_of_the_message[3],time_of_the_message[4],time_of_the_messa
ge[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|


=20
filepattern=3Dattachment.fileName.to_s.index(/NBH_|BBH_/)
if filepattern !=3D
nil
File.open(LOG_FILE,
"a+"){ |f| f.puts "=3D=3D=3D=3D=3D=3D#{attachment.fileName.to_s}"}

temp_filename =3D =
"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!=3D "." && x!=3D".." }
=20
attachment.SaveAsFile(temp_filename)
#we will now call
the fileupdater method of kpimumbaicontroller object
=20
@a.fileupdateupdater(temp_filename)

@file_c +=3D1
end
end
else
next
end

timed_last_time=3Dtimed_time_of_the_message
end
rescue Exception =3D> err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the
error at inner begin: ' + err }

raise

end




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

rescue Exception =3D> err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the
error at outer begin: ' + err }
#close @sqlconnection
raise
#msg =3D '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 =3D '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 =3D 'service_main left at: ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end

def service_stop

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

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

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

end

svc=3DDaemon.new
svc.mainloop

rescue Exception =3D> err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'Daemon failure: ' + err }

raise
end

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=



Sorry for a long code...

The problem is that my log file loooks like this
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
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
=3D=3D=3D=3D=3Dlast_time:Mon Oct 04 19:03:24 +0530 1971
=3D=3D=3D=3D=3Darr_last_time:197110419324+05301
=3D=3D=3D=3Dtimed_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
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

the inbox messagecount is returning 0 messages.

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

require 'win32ole'
outlook =3D WIN32OLE.new('Outlook.Application')
mapi =3D outlook.GetNameSpace('MAPI')
inbox =3D mapi.GetDefaultFolder(6)
file_c=3D1

#methods =3D []
#arrival_time=3Dinbox.Items(1).ReceivedTime
#b=3Darrival_time.to_a
#puts arrival_time
#require "parsedate.rb"
#include ParseDate
#formatted_date=3Dparsedate(arrival_time)
#p formatted_date
puts "#{inbox.UnreadItemCount}:so many unread messages"
puts "#{inbox.Items.Count}:so many messages"
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

i get output like a champ
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
484:so many unread messages
11398:so many messages
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D


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


Br

Rajib




4 Answers

BENI

4/9/2008 11:47:00 AM

0

On Apr 9, 12:34 am, "Nation, Carey" <Carey.Nat...@turner.com> 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 http://support.microsoft.com... 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.

.....




James Tucker

4/9/2008 12:33:00 PM

0


On 9 Apr 2008, at 12:50, BENI wrote:
> On Apr 9, 12:34 am, "Nation, Carey" <Carey.Nat...@turner.com> 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.

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

>
>
> 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 http://support.microsoft.com... 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.

> 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.
>
> ....


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

Phillip Gawlowski

4/9/2008 1:37:00 PM

0

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

James Tucker wrote:
|> 2>Also I found this link http://support.microsoft.com... 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 Gawlowski
Twitter: 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....

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

James Tucker

4/9/2008 2:21:00 PM

0


On 9 Apr 2008, at 14:37, Phillip Gawlowski wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> James Tucker wrote:
> |> 2>Also I found this link http://support.microsoft.com...
> 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..

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

>
>
> - --
> Phillip Gawlowski
> Twitter: 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....
>
> iEYEARECAAYFAkf8xogACgkQbtAgaoJTgL+cdwCdH0u+4u46DywWwXEuwqpH/n24
> CSQAn3GT6/qTAho6OPGiROp8Y24oBY7W
> =jMOm
> -----END PGP SIGNATURE-----
>